Notes
What happens when an integration fails?
The store keeps taking orders, because checkout does not depend on the ERP. What matters is what the integration does with the messages it cannot deliver: whether they wait in a queue and are sent again, or are dropped. A three-hour ERP outage at 40 orders an hour is 120 orders that have to arrive later, once each.
Updated
Can you keep taking orders?
Yes. A store saves an order in its own database and needs nothing from the ERP to finish checkout. When the integration or the ERP is down, the store keeps selling. What stops is the traffic between the systems, and each flow fails in its own way.
| Flow | While the integration is down | What it costs |
|---|---|---|
| Orders to the ERP | Orders stay in the store and wait | The warehouse does not see them. At 40 orders an hour, a 3-hour outage is 120 orders that are picked late |
| Stock to the store | The store shows the last figure it received | 14 pieces shown, 10 sold through another channel: up to 10 oversold |
| Prices to the store | The old price stays live | Orders are placed at yesterday's price and have to be honored or corrected |
| Shipment status to the store | No tracking code, no shipping email | Customers ask where the order is |
Orders are the flow where nothing may be lost. Stock is the flow where the delay itself does the damage: an order that arrives three hours late is still an order, a stock figure that is three hours old has already been sold against.
What happens to the messages
In an integration with a queue, a message is stored before it is sent and removed only after the receiving system confirms it. A failed attempt leaves the message where it is. Five things then decide the outcome.
Which errors are retried. A timeout, a 429 Too Many Requests and a 503 Service Unavailable pass by themselves. A 400 for an inactive item or a missing required field comes back identical on every attempt.
| Failure | Example | Handling |
|---|---|---|
| System unreachable | Timeout, 502, 503 |
Retry with growing pauses |
| Rate limit | 429, THROTTLED, SSS_REQUEST_LIMIT_EXCEEDED |
Wait the indicated time, retry |
| Record refused | 400, item inactive, customer on credit hold |
No retry. To the review list with the reason |
| Credentials expired | 401 |
Stop the flow, alert at once |
Backoff. The pause between attempts grows. An example schedule with five retries: 1 minute, 5 minutes, 15 minutes, 1 hour, 2 hours. Added up that is 201 minutes, so a message survives an outage of 3 hours and 21 minutes before it is given up. Retrying every second for three hours would be 10,800 calls per order against a system that is already in trouble.
A cap on attempts. After the last retry the message moves to the dead-letter queue. It keeps its original payload, so nothing has to be reconstructed from the store later:
{
"flow": "orders-to-erp",
"attempts": 6,
"first_attempt": "2026-10-02T13:00:12Z",
"last_error": "400 Item KB-2210 is inactive",
"payload": {
"order": "#10482",
"customer": "Bakker Installatie B.V.",
"lines": [ { "sku": "KB-2210", "quantity": 12, "price": "17.08" } ]
}
}
Replay. Once item KB-2210 is active again, the message is sent again from the dead-letter queue and processed as a new order.
One order per order. A retry after a timeout is the classic source of a second sales order: the ERP created the first one and the confirmation got lost. The integration sends the store order number as an external ID and checks for it before it creates anything. More on this in duplicate customers and duplicate orders; the retry mechanics per system are in API throttling, 429s and backoff.
The sending side gives up at some point too. Shopify waits 5 seconds for an answer to a webhook, retries 8 times over 4 hours and then removes a subscription that was created through the Admin API. If the receiving end is down for an afternoon, the messages of that afternoon are gone and no new ones follow. A scheduled run that asks for all orders since the last processed one recovers them, as described in webhooks are not a guarantee.
After recovery the backlog has to pass through the same rate limit as normal traffic. 120 orders at 4 calls each are 480 calls. Against an ERP that allows 60 calls a minute, the backlog takes 8 minutes if nothing else runs.
When the two systems disagree
A failure is not always an outage. Both systems are up, both hold a value for the same field, and the values differ. Three cases come up in every store to ERP integration:
- A customer changes the delivery address in the store at 10:02. Customer service corrects the same address in the ERP at 10:04. The sync runs at 10:05.
- The ERP pushes a new price of 12.50 while a customer has the item in the cart at 11.90.
- The warehouse sells the last piece at 14:00. The store sells the same piece at 14:01, before the stock update arrives.
The outcome has to be predictable, and that takes one rule per type of data:
| Data | Rule | Result in the example |
|---|---|---|
| Stock | ERP or warehouse system wins | The order of 14:01 is accepted and flagged as a backorder |
| Price | ERP wins for the catalog, the order keeps its own price | The cart order stays at 11.90, the next one pays 12.50 |
| Customer address | Last write wins, by timestamp | The ERP edit of 10:04 stays, the store edit of 10:02 is logged as overwritten |
| Customer address, stricter | Manual review when both sides changed within 5 minutes | Both versions on a list, one person picks |
| Order status | ERP wins | A cancellation in the store after shipment is refused |
Last write wins needs clocks that agree. A store timestamp in UTC and an ERP timestamp in local time without a zone are two hours apart in summer in Amsterdam, and the wrong edit wins.
How you find out
An outage is the easy case: every call fails and the queue grows. A healthcheck that runs every five minutes looks at two things, the time of the last successful run and the number of messages waiting, and sends an alert to the place where the team already works. In the three-hour example the alert goes out at 13:05, five minutes after the first failed order.
The failures that cost more are the ones without an error. Standard connectors and iPaaS platforms document several of these in their own help pages:
| Failure without an error | What you see | How it is found |
|---|---|---|
| An item without a mapping record is skipped | Stock of that item never changes in the store | Daily comparison of item counts on both sides |
| A flow paused for maintenance resumes with a wrong "last run" timestamp | Records from around the pause are missing | Compare record counts for that window after every pause |
A throttle error arrives inside a 200 OK |
The update looks sent and was not applied | Read the response body, not only the status |
| A webhook subscription is removed after 8 failed deliveries | Orders stop arriving, no call fails | Check that the subscription exists, every run |
| A bulk retry before the cause is fixed | Partial records in the ERP | Fix the cause first, then replay |
Each of these has the same shape: the integration reports success and the data is wrong. A check on the result finds them: a daily comparison of counts and values in both systems, per flow.
Targets to hold an integration to
"It works" is not measurable. Three figures are, and they can be read from the log of any integration that keeps one:
| Target | Example value | At 6,000 orders a month |
|---|---|---|
| Time from order placed to order in the ERP | Within 5 minutes | Measured per order |
| Error rate | Fewer than 2 per 1,000 records | At most 12 orders a month on the review list |
| Replay success | 98% or better | Of those 12, fewer than 1 needs manual entry |
The sum for the last row: 2% of 12 is 0.24, about one order every four months that someone types in by hand. The values are examples. The point is that each one is a number that a log can confirm or contradict.
Failure responses and a NetSuite retry example
Systems go down, time out and throttle. The integration is built so that a failure delays data and never loses it.
| Failure | What happens |
|---|---|
| Target system down or slow | the message stays in the queue and is retried with growing pauses |
| Rate limit reached | the integration reads the wait time from the response and continues after it |
| A record is rejected | the record goes to the error list with the reason; the rest of the run continues |
| A file is late or short | the run is held and an alert goes out |
| Retries run out | the message is kept with its original content and processed again after the fix |
A rate-limited answer from NetSuite's REST API looks like this:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
{
"title": "Too Many Requests",
"status": 429,
"o:errorDetails": [
{"o:errorCode": "CONCURRENCY_LIMIT_EXCEEDED"}
]
}
A Standard NetSuite account allows 5 concurrent requests, shared by every integration on the account. The order waits for a free slot instead of failing. An order retried after a timeout carries the same external ID, so NetSuite updates the existing sales order instead of creating a second one.
What this means for your integration
We build every integration with a queue, retries with growing pauses, a check against duplicates and a dead-letter queue, and then we host and run it. Monitoring is part of that: a failed run raises an alert on our side, and we fix it when the cause is a changed API or a changed file on the source side. In the dashboard you see each message with its attempts and its final state, and you can look up what happened to a single order.
The conflict rules per type of data are set with you before go-live, and a dry run shows what the integration would change before it writes anything. That part is described on dry run and approval. The flows themselves are on integrations, and the order flow with its fields on orders, customers and shipping. Tell us which systems you run and what went wrong last time.
Frequently asked questions
Can my store keep taking orders when the integration is down?
Yes. The store saves the order itself and does not need the ERP to complete checkout. While the integration is down the order waits: it has not reached the ERP, so the warehouse does not see it yet. The risk during the outage is on the stock side, because the store keeps showing the last stock figure it received.
Are orders lost when the ERP is offline?
Not when the integration has a queue. Each order is stored before it is sent and stays stored until the ERP confirms it. Failed attempts are repeated with growing pauses. An order that still fails after the last attempt goes to a dead-letter queue with its original content and can be sent again once the cause is fixed.
Will a retry create a duplicate order?
It does when the integration sends the same order again without checking. A timeout is the usual cause: the ERP created the order and the confirmation never arrived. The integration prevents this by sending the store order number as an external ID and looking for it before creating anything. The second attempt then finds the first order and stops.
How do I know a sync has failed?
A healthcheck that runs every five minutes checks two things: whether the last run succeeded and whether the queue is growing. When either is off, an alert goes to the channel your team reads, with the flow and the error. Failures that raise no error, such as a skipped item, are found by a daily comparison of both systems.
What is a dead-letter queue?
It is the place where a message goes after its last failed attempt. The message keeps its original payload, the error of the last attempt and the number of attempts. Nothing is deleted. After the cause is fixed, for example an inactive item is reactivated in the ERP, the message is replayed and processed as if it had just arrived.
What happens when both systems changed the same record?
A rule decides, and the rule is set per type of data before go-live. Stock and prices follow the ERP. An order keeps the price it was placed at. For customer data the options are last write wins, ERP wins, or a review list where a person picks. Without a rule the outcome depends on which sync happens to run first.
Tell us what you need
Tell us which systems you use and what needs to work better. We reply personally within one working day. We help you define the work, then agree the price and timing before you commit.
- You know the price and the timeline before you commit to anything
- We work out the connection that takes the work off your hands
- We handle the build, hosting, monitoring and maintenance
- Your team has less information to retype and fewer discrepancies to chase