Skip to main content

E-Commerce Tips

Magento-to-SAP Integration: What Actually Breaks

Stock drift, pricing mismatches, order sync gaps, and the master-data decisions that determine whether a Magento-to-SAP integration holds under load.

Magento-to-SAP Integration: What Actually Breaks

· Danny Khow, CEO, Bridzia Sdn Bhd

Magento-to-SAP integrations rarely break at the connection layer. They break because nobody decided, field by field, which system owns the truth, and what should happen when the two disagree at three in the morning during a promotion.

Moving a payload between Adobe Commerce and SAP is a solved problem. What is not solved by default is ownership, ordering, failure handling, and reconciliation. Bridzia has spent 14 years on Adobe Commerce, building Magento-to-SAP integrations across the Finance, Inventory, and Warehouse modules for retail clients, and the same short list of failures turns up on nearly every project. Here is what they are and how to design them out.

Stock drift: the storefront and the warehouse stop agreeing

Operations notices that the website says four in stock and the warehouse says none. Two separate causes get blamed on one bug.

The first is that SAP's stock figure is not a sellable figure. Unrestricted stock in a plant or storage location is not what a storefront may promise. Between the two sit allocations against open deliveries, blocked and quality-inspection stock, goods in transit, and whatever safety buffer the supply chain team keeps. Sync the raw quantity and you are publishing a number that was never meant to be sold against.

The second is that the two systems decrement at different moments. Adobe Commerce reserves quantity when the order is placed. SAP typically reduces stock when the delivery is posted and goods issue happens, which may be hours later. During that window the figures differ legitimately, and a naive sync overwrites a correct reservation with a stale warehouse number.

Design around it by defining sellable quantity as an explicit formula, agreed with the supply chain team and calculated on the SAP side. The storefront receives one number and does no arithmetic of its own. Publish frequent deltas plus a full snapshot on a slower cycle, stamp every message with a source timestamp or sequence number, and discard out-of-order messages instead of applying them. Then decide, before build, whether zero sellable stock blocks checkout or creates a backorder, because those are different order flows in SAP.

Pricing: SAP owns the price, the storefront owns the promotion

The usual arrangement is that SAP is the system of record for price while marketing needs promotional pricing SAP knows nothing about. That works until both systems write to the same field, at which point prices flap between two values on a schedule nobody can explain.

Price is not one value. It is at least three: the base price SAP owns, the promotional price the shopper sees (Magento catalogue rules, cart rules, tier and customer group pricing), and the price actually charged with the order. Keep those separate and the conflict disappears. SAP writes only to the base price attribute. The Magento rule engine computes everything on top of it and never writes back. The order then carries per-line prices and totals as charged, and SAP accepts them rather than recalculating from condition records. If finance insists on revalidation, agree a tolerance and a workflow for lines outside it, otherwise every promotional order becomes a manual exception.

The unglamorous half of this is rounding. Two systems with different decimal precision, rounding direction, and tax calculation order (per line against per document) will eventually produce totals a cent apart, and a cent is enough for a document to be rejected in the Finance module. Fix precision, rounding, and tax base during architecture, then test with the worst basket you can construct: a percentage cart discount spread across mixed tax rates with a discounted shipping line on top.

Order sync gaps: the order that exists in exactly one system

An order is placed, transmission to SAP fails. The obvious version is easy: a clear error, an alert, a retry. The dangerous version is ambiguity. The request timed out after SAP had already created the document, so the order exists there and the storefront does not know. Retry blindly and you have two sales orders, which become two deliveries and two invoices, unpicked by hand in finance three weeks later.

Idempotency is not optional here. Send a stable external reference with every order, normally the Magento increment ID, and have the SAP side check for an existing document with that reference before creating anything. If one exists, return its document number rather than creating a second. Retries then become safe by construction, which is what lets you retry aggressively.

Just as important: do not transmit the order inside the checkout request. Write it to an outbox in the same database transaction that commits the order, and let a worker transmit it. Checkout stops depending on ERP availability, and every order gains an explicit state: queued, sent, acknowledged with a document number, or failed with a reason. If you cannot answer "which orders are not yet in SAP" with one query, you do not have a sync model, you have hope.

Retries that make the outage worse

Retry logic causes roughly as many incidents as it prevents. Two patterns do most of the damage: the immediate fixed-interval retry loop, which turns a brief interface outage into a self-inflicted denial of service once the queue backs up, and infinite retry of a message that can never succeed, which parks a poison payload at the head of the queue and blocks everything behind it.

Classify failures instead. Network timeouts, lock contention, and a temporarily unavailable interface are retryable: use exponential backoff with jitter and a hard attempt cap. Validation failures such as a missing customer master record, an invalid material, or a closed posting period will fail identically forever, so route them to a dead-letter queue holding the raw payload and the real error text, and alert someone. Add a circuit breaker so the queue backs off from an interface that is plainly down and drains at a controlled rate when it returns. Preserve ordering where it matters, usually per entity rather than one global sequence, so a cancellation can never overtake the order it cancels.

Master data: the record that does not exist on the other side

Most rejected orders are master data problems wearing an integration costume. A product created in Magento but never extended in SAP for that sales organisation. A customer with no corresponding account. A unit-of-measure mismatch where the storefront sells singles and the sales unit is a case of twelve. A shipping method with no mapping to a document type.

Decide ownership per object rather than per system. In practice SAP owns material master, base price, stock, and the customer's financial identity. Magento owns descriptions, imagery, categories, SEO metadata, reviews, and merchandising. Then enforce it. A nightly ERP push that silently overwrites hand-written copy and meta descriptions is the most demoralising bug in this category: it destroys real work quietly, and the SEO team finds it weeks later.

Keep an explicit mapping table keyed on a stable identifier rather than string-matching on SKU, since SKUs get renamed and re-cased. Decide what happens to a record that exists on one side only: skipped silently, flagged in a report, or blocked from sale. The cost of getting this wrong is not only accounting. Segmentation, abandoned-cart flows, and on-site personalisation built through EC Intelligence inherit whatever the integration produces, so half-synced orders resurface as wrong lifetime-value figures and badly aimed campaigns.

Cadence: batch against near-real-time is not one decision

Asking whether the integration should be real time or batch is the wrong question, because the answer differs per object.

Event-driven

Orders, cancellations, shipment and status changes, and stock movements on fast-moving lines. The cost of delay here is measured in oversells and support tickets.

Scheduled

Full product master, full stock snapshots, price list loads, invoices, and credit memos. Pretending these bulk operations are events produces tens of thousands of messages in a nightly window the ERP was never sized for.

Near-real-time has a cost, and the ERP team pays it in interface throughput, table locking, and background job windows. Agree volumes with them before designing anything. A campaign repricing tens of thousands of SKUs at midnight has to arrive as a controlled batch, not a message storm competing with order transmission for the same capacity.

Reconciliation: the job most integrations never build

Every integration drifts. Assume it, and build the detector rather than the denial. A workable baseline is a nightly comparison of sellable stock and base price across the active catalogue, with a diff that auto-corrects inside an agreed tolerance and alerts outside it. Add a daily order-level check comparing counts and values on both sides, listing storefront orders with no ERP document and the reverse.

The output must be a short report a named person reads, not another log file. Reports that are usually empty get noticed when they are not.

The failure modes that only appear under load

All of the above holds at normal volume, and is invariably tested at normal volume. The interesting failures arrive during a campaign, when queue depth grows faster than the workers drain it and stock refreshes sit behind a bulk price push. Load-test the integration, not just the storefront, and decide in advance what gets shed when capacity runs short. Stock refresh frequency usually loses to order transmission.

The related discipline is keeping the ERP off the request path: nothing in add-to-cart, checkout, or order placement should wait on a system you do not control. Bridzia has maintained Guardian Malaysia's Adobe Commerce platform for more than eight years, through a revamp that improved site performance by 200% and lifted sales by 10%, and page speed of that kind is not compatible with synchronous ERP calls in the customer's path.

Marketplaces add a second synchronisation layer, since Shopee, Lazada, and TikTok Shop each hold their own view of stock and orders. That is what WOW Sync, Bridzia's own marketplace synchronisation technology, exists to solve, and a past project write-up covers how that side fits together with in-store and warehouse inventory.

What actually determines whether it holds

Per-field ownership, agreed and documented. One sellable-stock formula, calculated in one place. One writer per price field. Idempotent order transmission keyed on a stable external reference. Retries classified into retryable and terminal, with a dead-letter queue someone monitors. A cadence chosen per object. Reconciliation running from day one rather than added after the first bad month.

None of it is glamorous, and all of it is cheaper to decide during architecture than during UAT. The integration is the hardest part of an Adobe Commerce build to change once orders flow through it.

Bridzia builds and maintains Adobe Commerce (Magento) platforms from Kuala Lumpur for retail and FMCG brands across Asia, with more than 100 projects delivered. If you are planning an SAP integration, or working out why an existing one keeps drifting, get in touch.