# Event-Driven ERP Integration: Architecture That Holds Up

> Source: https://netray.co/erp-help/cto-event-driven-erp-integration-architecture
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: ERP Help

## Short answer

Use events when several systems must react to ERP changes quickly and you want to stop polling. Get events from the ERP's native mechanism where one exists, otherwise from change data capture, and design every consumer to be idempotent and tolerant of reordering. Keep the ERP as the system of record and treat events as notifications, not as the ledger.

## Kind

cio

## System

it-leadership

## Erp

ERP integration (vendor-neutral)

## Module

Event-Driven Integration

## Query

event-driven architecture for ERP integration how to design it

## Alternate Queries

- ERP events Kafka integration pattern
- outbox pattern ERP integration
- ERP webhooks vs polling
- publish ERP business events to other systems

## Applies To

ERPs with native eventing (Infor ION BODs, SAP Event Mesh and business events, Dynamics 365 business events, Oracle Fusion business events, NetSuite SuiteScript user events) and any ERP via CDC.

## Steps

### How to design event-driven ERP integration

**Items:**

Identify the events the business actually needs: sales order released, receipt posted, work order completed, item changed. Resist publishing every table change.

Find the ERP's native event source first: ION BODs on Infor, SAP business events through Event Mesh, Dynamics business events, Oracle Fusion business events, or a SuiteScript user event or workflow that calls out from NetSuite.

If no native source exists, capture changes with log-based CDC, or write events to an outbox table in the same database transaction as the business change and publish from it.

Publish to a broker with durable storage: Kafka, RabbitMQ, Azure Service Bus, AWS SNS/SQS or the vendor's own bus. Choose retention long enough to replay after a consumer bug.

Define a stable event contract with an ID, type, version, timestamp, entity key and a minimal payload. Prefer sending the key and fetching current state from the ERP when freshness matters.

Make consumers idempotent: store processed event IDs or use natural idempotency keys, so duplicate delivery never creates a second order or receipt.

Handle ordering explicitly. Partition by entity key where ordering matters, and use version or timestamp checks to discard stale updates.

Add a dead-letter queue, alerting on lag and a replay procedure, and test them before go-live.

## Sections

### Where ERP events come from

**Body:**

Native events are the safest source because the ERP decides when a business change is complete. Infor ION distributes BODs (Business Object Documents) through its messaging layer, SAP exposes business events that can flow through SAP Event Mesh or Integration Suite, and Dynamics 365 Finance and Operations has a business events framework that targets Service Bus, Event Grid or HTTPS endpoints. Check which of your transactions are actually covered, since coverage is rarely complete.

Where coverage is thin, log-based CDC (Debezium on SQL Server, Oracle or PostgreSQL) emits row-level changes with low overhead. The catch is semantics: a row change is not a business event. A sales order release may touch six tables across several commits, so you need logic to assemble the row changes into one meaningful event.

Cloud SaaS ERPs without database access, such as NetSuite, rely on in-product hooks: a User Event script on aftersubmit, a workflow action or a scheduled saved search that calls an external endpoint. Remember governance limits and make the callout asynchronous, because a slow external call inside the transaction slows every user.

### The outbox pattern and why dual writes fail

**Body:**

A common mistake is to update the ERP and then publish a message in application code. If the process dies between the two steps, the ERP changed but no event was sent, or the reverse. This dual-write problem is why events silently disappear in production and why finance and the warehouse drift apart.

The transactional outbox fixes it. Write the business change and an outbox row in the same database transaction. A separate relay reads the outbox and publishes to the broker, marking rows sent. Delivery becomes at-least-once, which is why consumers must be idempotent. This pattern fits custom extensions on ERPs where you control a database, such as customisations on SyteLine or Dynamics.

For packaged ERP code you cannot modify, the equivalent is to treat the vendor's own change log or CDC stream as the outbox and build the relay around it.

**Code:**

-- Outbox table written in the same transaction as the business change
CREATE TABLE integration_outbox (
  event_id     UNIQUEIDENTIFIER PRIMARY KEY,
  event_type   VARCHAR(80)  NOT NULL,
  entity_key   VARCHAR(80)  NOT NULL,
  payload_json NVARCHAR(MAX) NOT NULL,
  created_at   DATETIME2 DEFAULT SYSUTCDATETIME(),
  sent_at      DATETIME2 NULL
);

### Consumers: idempotency, ordering and replay

**Body:**

Brokers deliver at least once, so duplicates will happen. Give every event a unique ID and have the consumer record processed IDs, or key downstream writes on a natural identifier such as the external order number so a repeat is a no-op. Without this, a retry after a timeout creates duplicate receipts.

Ordering is weaker than most designs assume. Kafka preserves order only within a partition, so partition by the entity key. Even then, include a version or modified timestamp and ignore updates older than what you already applied. For the highest-value flows, send only the key and have the consumer read the current ERP state.

Plan for replay. When a consumer has a bug, you will want to reprocess a week of events. That requires retention, deterministic consumers and a way to mark side effects, such as emails or ERP postings, so replay does not repeat them.

## Pitfalls

- Publishing from application code after the ERP commit. A crash between the two creates silent data loss; use an outbox or native events.
- Treating row-level CDC as business events. Consumers then see half-complete transactions and must reconstruct meaning themselves.
- Making the ERP callout synchronous. A slow external endpoint blocks users and can hit governance or timeout limits.
- Assuming exactly-once delivery. Design every consumer for duplicates and out-of-order arrival.
- Fat payloads that duplicate ERP state. Stale copies cause conflicts; send keys and fetch when freshness matters.
- No dead-letter queue or lag alerts. Failures sit unnoticed until a department notices missing data.

## Ai Angle

Events also help AI assistants stay current without constant polling, for example refreshing an index or cache when an item or order changes. ERPray reads live ERP data in read-only mode and shows the query it ran, so event feeds are an optimisation for retrieval freshness, not a requirement. Any action an agent proposes still goes through human approval before it writes through the ERP's API.

## Faq

### Is event-driven integration worth it for a mid-sized manufacturer?

**Answer:** Often not at first. If a few systems exchange data on a schedule, scheduled sync with good monitoring is simpler. Events pay off when several consumers need to react quickly to the same changes, or when polling load on the ERP becomes a problem.

### Do I need Kafka for ERP events?

**Answer:** Not necessarily. A managed queue or the ERP vendor's bus (Infor ION, SAP Event Mesh, Azure Service Bus) can handle moderate volumes. Choose Kafka when you need replayable history, high throughput or many independent consumers, and have the skills to operate it or buy it managed.

### How do I get events out of NetSuite?

**Answer:** Use a User Event script on aftersubmit, a workflow, or a scheduled saved search to send an asynchronous callout or to write to a queue. Mind governance units and avoid blocking the user transaction. Alternatively poll with SuiteQL on a last-modified field for lower-priority flows.

### What is the difference between CDC and business events?

**Answer:** CDC emits row-level changes from the database log. A business event represents a completed business fact such as order released. One business event can span many row changes, so CDC needs assembly logic. Native ERP events are usually closer to business meaning but have narrower coverage.

## Search terms

event-driven ERP integration, ERP events Kafka, outbox pattern ERP, ERP business events, Infor ION BOD events, SAP Event Mesh integration, Dynamics 365 business events, ERP webhooks, ERP change data capture Debezium, idempotent ERP integration

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
