Every plant that’s run MES and ERP side by side for more than a couple of years has a story about the sync loop that wouldn’t stop. A work order status flips back and forth between “in process” and “released” every few minutes. A material master field gets corrected in ERP, overwritten by MES on the next poll, corrected again, overwritten again. Nobody planned this. It happened because two systems were each configured to believe they were in charge of the same piece of data, and the integration middleware just faithfully carried out both sets of instructions.
The fix isn’t a smarter integration tool. It’s a decision — made explicitly, domain by domain, and documented — about which system is the system of record for which data, and enforcing that decision so hard that the other system is architecturally incapable of overwriting it.
Why bidirectional sync feels right and goes wrong
The instinct to make everything bidirectional comes from a reasonable place: ERP owns planning and financials, MES owns execution, and surely both need to update shared records as things change. But “both can update” is a different statement from “both should update the same field.” When two systems can independently write to the same attribute, you no longer have a single source of truth — you have two sources racing each other, and the loser is whichever one wrote last before the next poll cycle.
This gets worse under high-frequency integration patterns. If your middleware uses short polling intervals, or you’ve moved from batch nightly interfaces to near-real-time messaging via MQTT, Kafka, or an ESB, a small logic conflict that used to surface once a day now surfaces every few minutes. Faster integration exposes design flaws faster. That’s the trap: the same modernization that makes your plant more responsive also makes an unresolved ownership conflict a lot more visible, a lot faster.
Assign a system of record per domain, not per interface
The right unit of analysis isn’t “the MES-ERP interface.” It’s each individual data domain. Treat these as separate decisions:
Material master
ERP should almost always own this. Material numbers, base units of measure, procurement attributes, and costing data live in ERP for a reason — they touch purchasing, finance, and planning. MES should read material master data and cache it locally for execution, but never write back core attributes. If MES needs a plant-specific attribute ERP doesn’t track well (a fixture ID, a line-specific yield factor), model that as an MES-owned extension field, not a shadow copy of an ERP field.
Routing and BOM
This one’s more nuanced. ERP typically owns the engineering routing and BOM — the “should be” process. MES, especially in an ISA-95/ISA-88-aligned architecture, often maintains a more detailed execution-level routing with equipment-specific parameters, work instructions, and quality checkpoints that ERP has no business tracking. The rule: ERP owns the master routing structure and revision control; MES owns execution detail layered on top of it. Changes to the master routing flow one-way, ERP to MES. MES-specific execution parameters never flow back as routing changes in ERP — they stay local or get exposed through a separate, clearly-labeled interface.
Work order status
This is the domain that causes the most damage when it’s wrong, and the answer is almost always that MES owns execution status. Once a work order is released to the shop floor, MES should be the sole writer of status transitions — released, in process, completed, scrapped. ERP consumes those status updates for scheduling and financial postings but does not independently flip status based on its own logic (like a goods-issue posting silently marking something complete). If your ERP configuration allows both automated batch jobs and MES feeds to change order status, you already have the two-way war; you just haven’t noticed the casualties yet.
Inventory
Split this by location and transaction type. ERP typically owns the “official” on-hand balance for financial and planning purposes. MES owns real-time consumption and production reporting at the point of use — component consumption, scrap, WIP movement. The integration should be a one-way transaction feed from MES to ERP (a posting, not a shared balance field), with ERP performing its own reconciliation logic rather than accepting a raw overwrite of quantity fields.
Build the technical guardrails, not just the policy
A documented rule that either system can still technically violate isn’t a guardrail, it’s a suggestion. A few things that actually enforce ownership:
- Make the non-owning system’s copy of the field read-only at the interface layer, not just by convention. If MES can technically write to a material master field, eventually someone’s script will.
- Use middleware to timestamp and log every write with its source system. When something looks wrong, you need to know in thirty seconds which system touched it last, not spend an afternoon in log files.
- Model shared identifiers (work order number, material number, batch ID) as immutable keys that both systems reference but only one system generates. Letting both systems generate IDs independently is its own special kind of chaos.
- Add conflict-detection alerts, not just conflict-resolution logic. If the non-owning system attempts a write to an owned field, that should trigger a visible exception, not a silent overwrite.
The part that’s changing: ERP release cadence is now your problem
Integration middleware built five or six years ago generally assumed ERP moved slowly — annual support packs, predictable regression testing windows, plenty of lead time to check whether an API contract changed. Cloud-first ERP has broken that assumption. SAP’s move toward more frequent cloud releases for S/4HANA Cloud, and Microsoft’s continuous update cadence for Dynamics 365, mean the API surface, field behaviors, and even default status logic your integration depends on can shift multiple times a year rather than once.
The practical implication: you can no longer treat your MES-ERP interface as “built and stable.” Build a lightweight regression suite specifically for your system-of-record rules — a set of test transactions that verify material master stays read-only from MES, work order status transitions stay one-way from MES to ERP, and inventory postings don’t get double-counted — and run it against every ERP release, not just major version upgrades. Ask your ERP vendor or partner for release notes on API and status-workflow changes as a matter of routine, the same way you’d track firmware changes on a PLC.
If your integration platform (Boomi, MuleSoft, SAP Integration Suite, Azure Integration Services, or a custom middleware layer) supports contract testing or schema validation, use it to fail loudly when an ERP release changes a field type or workflow trigger you depend on, rather than finding out three days later when a work order feed silently stops updating.
What done right actually looks like
You’ll know the design is working when a controls engineer can tell you, without checking documentation, which system owns a given field for every major domain — and when an ERP cloud update lands, your regression suite catches any behavioral drift before the next shift starts, not after a supervisor notices work orders stuck in the wrong status. That’s not a glamorous outcome. It’s just the difference between an integration that quietly works and one that’s one bad Tuesday away from a shop-floor fire drill.
This article was written with the assistance of artificial intelligence. While we aim for accuracy, the information may be incomplete, out of date, or incorrect, and should be independently verified before you rely on it for any decision. It is provided for general information only and does not constitute professional advice.
