Don't sync everything: one owner, one direction per field
When you bridge an ERP and a CMS, the cleanest contract is to make every field owned by exactly one system, syncing in exactly one direction.
TL;DR
When two systems share data (an ERP and a CMS, an admin app and a public site, a master DB and a cache), the cleanest contract is: one owner and one direction per field. The moment a field is editable in both, you’ve signed up for a conflict you’ll resolve forever.
This is the rule that turned a Sanity-on-top-of-NetSuite setup (case study) from “which value is right?” into something operators can actually trust.
The trap
When you pull ERP data into a CMS, the tempting move is to make everything editable. It feels generous. It immediately creates a conflict: if a marketer edits a weight in the CMS and the ERP later re-syncs, whose value wins? Same question for descriptions, categories, SEO, pricing — every shared field. You end up writing a merge policy, and the merge policy is where bugs live.
The rule
For every field, decide two things and write them down:
- Who owns it — the system of record.
- Which direction it syncs — owner → consumer, never both ways.
Then enforce the rule in the schema, not in a wiki:
- Operational/commercial data (item code, class, weights, dimensions, pallet layout, barcodes, pricing) — ERP owns it. Syncs one-way into the CMS. Read-only in the CMS UI, written only by the sync process via an API token.
- Marketing/presentation data (descriptions, imagery, recipes, SEO, cross-links) — CMS owns it. ERP never touches it.
In the CMS schema this means two visibly different sections: operational fields grouped into a “locked” section (read-only in the UI), and marketing fields into an “editable” section listed first. A living field-ownership map documents every field, its source, and its direction.
Why this works
- No “which value is right?” debates — the schema answers it before anyone asks.
- Editors get a clean, obvious surface — “this part is from the ERP, this part is yours.”
- The sync can run safely without ever clobbering human work, because it only writes into fields it owns.
- The next engineer onboards in an afternoon, because the rule is the schema.
How to apply it elsewhere
- Same as draft/publish in a CMS: data is owned by the editor, publish status is owned by the publish action; the published copy is read-only everywhere except the publish step.
- Same as app/cache: app owns writes, cache is read-only and rebuilt; never edit the cache directly.
- Same as frontend/backend for derived values: the backend owns the canonical number, the frontend renders it but never persists its own version.
If you notice yourself writing a merge policy, stop and ask: can I just pick an owner?
When not to use it
- Truly collaborative fields where both systems contribute new facts (e.g. one writes “submitted”, the other writes “approved”). Solution: split them into two fields, each with one owner. Don’t share one field.
- Migration windows where you genuinely need to write from both sides briefly. Treat it as temporary, write the cutover date down, and finish it.
The one-line version
Don’t sync everything. Decide who owns each field.