Event-Driven ERP Integration: Outbox, Idempotency, and Safe Replay

Design event-driven ERP integration with atomic outbox records, stable event identity, idempotent consumers, ordered processing, reconciliation, and controlled replay.

Edilec Research Updated 2026-07-13 Enterprise Systems

Event-driven ERP integration lets orders, receipts, invoices, inventory changes, and master-data events reach other systems without making every business transaction wait for remote services. The risk is partial success. An ERP commit can succeed while event publication fails, or a broker can redeliver after a consumer updates its database but before acknowledgment. In financially meaningful flows, a duplicate is not harmless transport noise; it can become a second posting, shipment, or payment.

A reliable design combines several controls. The transactional outbox binds business state and publication intent in one local commit. A relay publishes at least once. Stable event identity lets consumers detect repeats. Idempotent business operations prevent duplicate outcomes. Ordering is limited to the entity that needs it. Replay uses immutable scope and approvals. Independent reconciliation finds lost, stuck, or semantically rejected work that technical delivery metrics cannot prove.

Define the business event contract

Publish a fact that has happened, such as sales order released, not an imperative with ambiguous ownership. Define source, event ID, type, occurred time, subject or aggregate ID, schema version, producer revision, correlation and causation IDs, and business payload. CloudEvents standardizes context attributes and states that the combination of source and id identifies a distinct event; a resent duplicate may retain that identity. Use those semantics consistently across relays and adapters.

Keep sensitive data out of routing metadata because intermediaries and logs can expose context attributes. Include only payload needed by subscribers or provide a stable reference where consumers are authorized to retrieve more. Version meaning, not only shape. Changing an amount from gross to net under the same field name is breaking even if JSON validation passes. Document delete, reversal, correction, and late-arriving semantics.

IdentifierScopePurposeMisuse to avoid
Event IDOne published factDuplicate detection and auditGenerating a new ID on relay retry
Aggregate IDOrder, invoice, item, or accountPer-entity ordering and state lookupTreating it as globally ordered stream
Correlation IDBusiness journeyTrace related work across systemsUsing it as an idempotency key for every step
Causation IDTriggering command or eventExplain event lineageReplacing immutable source evidence
Consumer operation keyOne downstream side effectIdempotent result reuseDeduplicating unrelated actions from the same event

Commit business state and outbox atomically

Sequence diagram showing an ordering service committing an order and OrderCreated event in one database transaction before a background worker publishes the stored event to a message bus
The transactional outbox records business state and publication intent in one commit; a separate worker can then retry delivery without recreating the business transaction.

Insert the outbox record in the same database transaction and transactional scope as the ERP change. Microsoft describes the pattern as saving the business object and event together so both commit or roll back. If the ERP exposes only released business APIs and no shared transaction, use a vendor event framework, change feed, or supported extension point that provides equivalent post-commit evidence. Do not dual-write to a broker inside the business transaction and assume both systems will agree.

Six-stage event-driven ERP integration flow from local business commit and outbox creation through relay, broker delivery, idempotent consumption, controlled replay, and business reconciliation.
At-least-once delivery is safe when stable identity, local atomicity, idempotent outcomes, and reconciliation span the ERP boundary.

The outbox stores immutable event identity, aggregate, sequence or version, payload or payload reference, schema, creation time, partition key, and publishing status. Protect it from casual update. The transaction should not mark an event published; the relay owns delivery state. Retain enough history to investigate and replay, but archive according to financial, privacy, and storage requirements. Outbox cleanup must never overtake the slowest recoverable subscriber obligation.

Make the relay retry-safe and observable

The relay polls or consumes a change log, publishes, then records progress. A crash after publish but before progress can send the same event again. That is expected in an at-least-once design, so the event ID remains unchanged. Use leases or partition ownership to scale relays and preserve required per-aggregate order. Measure oldest unpublished age, backlog, publish attempts, broker acknowledgment, and outbox-to-broker latency.

A published marker is operational evidence, not proof that every subscriber applied the event. Broker retention and consumer lag need separate monitoring. On an unknown publish outcome, query broker-supported state only if it is authoritative; otherwise repeat with the same identity. Never create a replacement event merely to get past a stuck relay because that defeats deduplication and obscures whether two business facts exist.

Implement consumer idempotency around the outcome

A consumer should commit its inbox or processed-event record and business update atomically in its own datastore. On repeat delivery, it returns the recorded outcome without repeating the side effect. A uniqueness constraint on source and event ID closes concurrent races. For an event that drives several independent actions, use operation-specific keys so retrying notification does not repeat a ledger posting and one completed action does not suppress another.

Deduplication windows in brokers can reduce traffic but are not a complete business control; replay may occur after the window or through another channel. Build domain idempotency as well. Creating an invoice may be keyed by source order and invoice purpose, while applying a versioned inventory state can reject stale versions. External APIs need propagated idempotency keys or a durable adapter ledger before the irreversible call.

Failure pointPossible duplicateRequired controlReconciliation evidence
After ERP commit, before relayNo duplicate yet; event is pendingAtomic outbox and backlog alertCommitted transaction has one outbox fact
After broker accept, before relay checkpointSame event republishedStable event ID and consumer inboxBroker deliveries map to one event
After consumer update, before acknowledgmentConsumer sees event againAtomic inbox plus business updateOne downstream business outcome
After external side effect, before local recordPartner action may repeatPartner idempotency or pre-call operation ledgerPartner reference tied to operation key
During operator replayOld facts re-enter active flowImmutable scope, dry run, approvals, and rate limitExpected population equals applied or skipped outcomes

Limit ordering to the business entity

Global ordering sacrifices throughput and usually exceeds business need. Partition by stable aggregate when create, update, and cancel for one order must remain ordered. Include aggregate version so consumers can detect gaps, duplicates, and stale events. Cross-aggregate processes, such as order and payment, need an orchestrated workflow, explicit state machine, or reconciliation rather than assumptions about broker arrival order.

When a gap appears, pause that aggregate, retrieve missing state, or use a documented overwrite rule. Do not block every partition. Events can also arrive after a correction or snapshot, so define whether consumers apply deltas, replace state by version, or query the source. The choice determines replay safety. Commutative updates are easier to retry than increment commands that can apply twice.

Operate replay as a controlled migration

Specify source event IDs, time and aggregate filters, target consumers, reason, expected count, schema compatibility, rate, start and stop criteria, and approver. Produce a dry-run manifest and check current downstream state. Replay into an isolated topic or consumer mode when old events need transformation. Keep original identity for the same fact; if creating a new corrective fact, give it a new ID and explicit link to what it corrects.

Throttle against ERP, broker, consumer, and partner capacity. Observe applied, duplicate-skipped, rejected, dead-lettered, and pending counts. A technically successful replay can still produce wrong outcomes if historical schemas or business rules are interpreted using current logic. Pin the required handler version or transform deliberately, and record that decision. Stop when unexpected side effects or reconciliation drift appears.

Model reversal and compensation explicitly

A later failure may require a compensating business transaction rather than deleting prior events. Microsoft notes that compensation is application-specific and may not restore the exact original state because concurrent work can occur. For ERP flows, issue credit, cancel reservation, reverse posting, or open manual review through supported operations. Emit new facts that preserve history instead of editing the old event.

Define which actions are automatically compensatable, which need approval, and which are irreversible. Compensation handlers must also be idempotent. Track the original transaction, failed step, compensation state, financial reference, and human decision. A saga reported complete only after every forward step or approved compensation reaches a terminal, reconciled state.

Reconcile business populations end to end

Compare ERP committed facts, outbox population, broker publication, consumer acceptance, and final business records by event type, entity, period, company, and value. Technical counters reveal backlog, while business controls reveal missing invoices or mismatched amounts. Reconciliation should classify pending within service level, duplicate skipped, rejected, compensated, and unexplained. Only the last category represents unresolved integrity risk.

Give operations a transaction view keyed by business reference and event identity. It should show state without allowing arbitrary republish. Restrict replay and correction actions, require reason and approval, and preserve audit logs. Alert on age and materiality, not only raw queue depth; one stuck high-value settlement can matter more than thousands of low-risk telemetry events.

Key takeaways

  • Commit the business change and outbox intent in one supported local transaction.
  • Keep event identity stable across publication retries.
  • Make each downstream business operation idempotent with durable evidence.
  • Order by aggregate only where the domain requires it.
  • Replay immutable, approved populations under capacity controls.
  • Reconcile from ERP commit to final business outcome, including compensation.

Frequently asked questions

Can a broker guarantee no duplicate ERP transaction?

Not by itself. The ERP or external side effect may be outside the broker transaction. Use stable identity, consumer atomicity, domain idempotency, and reconciliation at the business boundary.

Should replay assign new event IDs?

Retain identity when redelivering the same fact. Assign a new ID only for a genuinely new correction or compensating fact, and link it to the original.

Can old outbox rows be deleted after publication?

Only after retention, replay, audit, and consumer recovery obligations are satisfied and archived evidence remains usable. Publication alone does not prove downstream application.

Conclusion

Event-driven ERP integration is dependable when duplication and delay are designed outcomes rather than surprises. Atomic outbox creation closes the commit-to-publish gap; stable identity and idempotent consumers bound redelivery; scoped ordering, governed replay, compensation, and business reconciliation protect material transactions. Together these controls let asynchronous flows scale without trading away financial and operational integrity.

Continue with related articles

Dead-Letter Queue Replay Without Repeating Side Effects

Run dead-letter queue replay as a controlled production change with failure classification, immutable evidence, correction strategy, idempotency proof, bounded redrive, observability, and audit.

Software Engineering · 15 min