Acro Commerce

Integration architecture

What should the storefront do when the ERP is unreachable?

Decide four things before launch and write them down: what price the storefront shows, what availability it claims, what it does about credit, and whether it can still take an order. The only one with a single correct answer is the last, because an order the storefront accepts and cannot store is revenue you have destroyed, so order capture queues and everything else degrades to a stated fallback.

What does "down" actually mean, and which kind are you designing for?

Nobody with something to sell publishes this page, because it starts by admitting that the ERP is sometimes unreachable. It always is, and the useful move is to be specific about how, because the five modes need different answers and only one of them looks like an outage.

A hard outage is the rare one. A planned upgrade or maintenance window is the common one, and it is scheduled, which means you can design for it precisely. Throttling is the one that surprises people, because the ERP is up and is refusing you. Slowness is the most damaging, because a request that eventually succeeds after 30 seconds has already lost the customer. And wrong is the worst of the five: the ERP answers quickly and confidently with stale or incorrect data, and nothing anywhere reports a problem.

Throttling deserves real numbers rather than hand-waving, because on Acumatica the limits are licensed. The Acumatica Licensing Guide dated April 2024 sets web API requests per minute at the highest consumption tier as 50 on Essentials, 100 on Select, 150 on Prime and 300 on Enterprise, with maximum concurrent API connections of 10, 10, 20 and no limit respectively, and API concurrency queue sizes of 5, 10, 20 and 40. It also states that "When the number of connections exceeds the maximum, the system will prevent additional users from logging in". Read that last sentence twice: a badly behaved storefront integration can lock your own staff out of the ERP. Check the current guide against your own contract, since these figures are from an April 2024 document.

The design consequence is that "is the ERP up" is the wrong question. The right one is "what does this page do when this specific call does not return in time", asked once per call.

Checked against: Acumatica Licensing Guide, April 2024: web API requests per minute, concurrent API connections and API concurrency by edition. Read 20 August 2026

What are the four decisions, and what is the safe default for each?

Four things on a B2B storefront depend on the ERP being reachable: the price, the availability, the credit position, and the order. Each needs a decided behaviour rather than whatever the code happens to do, and each has a different safe default because the harm from being wrong is different.

The table is the deliverable here. Take it into a room with the person who owns pricing and the person who owns credit, and fill in the third column with names. A degraded-mode policy that nobody signed is not a policy.

Degraded-mode defaults when the ERP is unreachable, and what each one costs
CriterionSafe defaultWhat that costs youWhat you must not do
PriceServe the last known good customer price from cache, with a maximum age you have decided, and let the buyer transact on it.You may honour a price that changed this morning. For most distributors that is a smaller loss than a lost order, and it is a decision the commercial owner should make, not the developer.Fall back to list price for a contract customer. Showing an account their undiscounted price is worse than showing no price at all.
AvailabilityServe the last known figure with the time it was read, shown to the buyer, and stop making promises the number cannot support.Occasional overselling on fast-moving lines, which your backorder process already handles.Show a live-looking stock figure with no age. A stale number presented as current is the one failure your customer will remember.
CreditAccept the order and hold it for review rather than approving or refusing it on stale data.A queue somebody has to work through when the ERP returns, and it must be somebody’s named job.Refuse a good customer at checkout because you could not read their balance. That is a support call, a lost order, and a relationship cost all at once.
Order captureAlways accept. Store the order locally with an idempotency key and post it to the ERP when the ERP returns.A queue, a retry policy, and somewhere to look when a message will not post. This is the part worth paying for.Make submission synchronous on the ERP. An order the storefront accepted and could not store is revenue destroyed, not delayed.

Why must order capture never depend on the ERP being up?

Because the asymmetry is enormous. A wrong price costs you margin on one order. A refused order costs you the order, and often the buyer’s willingness to try the website again, which is the thing the whole project was for.

The pattern is not exotic. The storefront accepts the order, writes it durably with an Idempotency means an operation can be repeated safely, so sending the same order twice produces one order rather than two. Integrations achieve it by attaching a unique key to each request that the receiving system uses to recognize a repeat. key derived from something stable such as the storefront order number, and returns a confirmation to the buyer that promises acceptance rather than ERP posting. A worker posts queued orders to the ERP and retries with backoff. If the ERP has already seen that key, the retry is a no-op rather than a second sales order.

The idempotency key is the part teams skip and it is the part that produces duplicate orders. A retry after a timeout is the classic case: the ERP received and committed the order, the response never arrived, the queue retried, and the customer now has two. Without a key that the ERP checks, retry safety and duplicate safety are in direct conflict and you will get to choose which failure you prefer.

Say the confirmation honestly. "We have your order, reference W-10432" is true even when the ERP is unreachable. "Your order has been placed in our system" is a claim about a system you cannot currently reach, and B2B buyers reconcile on references, so give them one that will survive.

What should the buyer actually see?

Degraded mode is a copy problem as much as an engineering one, and most implementations get the engineering roughly right and then fail in the interface by saying nothing.

The rule that works: never show a spinner where a sentence would do. A B2B buyer forgives a stated limitation and does not forgive a page that appears to be working and is not.

The list below is what to write before you need it. Writing these sentences in advance takes an hour and, unlike the code, they will be read by every customer who hits the condition.

  • A price shown from cache: name the account, show the price, and say when it was last confirmed. "Your price, confirmed at 08:40 today" is enough.

  • Availability shown from cache: show the figure and its age, and drop any delivery date you can no longer compute rather than showing an optimistic one.

  • An order accepted while the ERP is unreachable: confirm acceptance with a reference, state that the acknowledgement with confirmed availability follows, and give a time by which it will.

  • A credit-held order: tell the buyer it is held for review rather than implying it was refused, and say who will contact them.

  • A feature you have switched off, such as a live quote request: say it is temporarily unavailable and give the phone number. Buyers use the phone number, which is the point.

How will you know it happened?

Most mid-market ERP integrations are unwatched. They were commissioned by a project that ended, and the first report of a failure is a customer or a controller three weeks later. Degraded-mode design without detection is just a slower way of finding out.

Three signals are enough and none of them needs a platform purchase. Count the calls that fell back, not the errors, because a fallback is a success from the code’s point of view and is exactly the event you want to see rising. Watch the age of the oldest item in the order queue rather than the queue length, since a queue of two that is six hours old is a worse problem than a queue of two hundred draining normally. And alert on the absence of the nightly job, not only on its failure, because the failure you actually get is the job that never ran.

Then decide who receives that alert on a Saturday. If the answer is a shared mailbox, you do not have monitoring, you have a log.

One honest note on planned windows. ERP upgrades and maintenance windows are scheduled events, so the cheapest resilience available is knowing when yours are and putting the storefront into a stated degraded mode deliberately rather than discovering it. That costs a calendar entry.

What is the one-page policy to write before launch?

Six lines, agreed by the people who own the money rather than by the people who own the code. If you write nothing else from this page, write these.

Every one of the six is a commercial decision that a developer will otherwise make by default, at 2am, under time pressure, in a way nobody reviewed.

  1. Maximum age we will serve a cached contract price at, and what we do when it exceeds that.

  2. Maximum age we will serve an availability figure at, and whether we keep selling past it.

  3. Whether checkout stays open when credit cannot be checked, and who works the resulting hold queue.

  4. How long an order may sit in the queue before somebody is told, and who that is.

  5. What we tell the buyer in each case, written as sentences and signed off before they are needed.

  6. Who is called, out of hours, when the queue stops draining.

The wider picture

This page answers one narrow question. Acro Commerce covers the strategy around it.

Common questions

Should the storefront keep selling when the ERP is down?
Yes, in almost every B2B case, with stated fallbacks. The alternative is refusing orders from account customers who have already agreed prices with you, which converts a technical problem into a commercial one. Serve the last known price and availability with their age shown, queue the order, and hold anything that needed a credit decision. The exception is any product where selling something you cannot supply has consequences beyond a backorder, such as controlled or allocated stock, and that exception should be a named list rather than a general policy.
How do we avoid duplicate orders when the ERP comes back?
Give every order a stable Idempotency means an operation can be repeated safely, so sending the same order twice produces one order rather than two. Integrations achieve it by attaching a unique key to each request that the receiving system uses to recognize a repeat. key before the first attempt, derived from something the storefront owns such as its order number, and have the posting step check whether that key already exists in the ERP before creating anything. The failure this prevents is specific and common: the ERP commits the order, the response is lost to a timeout, the queue retries, and the customer gets two. Without a key, retry safety and duplicate safety pull against each other and you have to pick one.
What are Acumatica’s API limits, and can our storefront trip them?
Yes, and the numbers are licensed rather than universal. The Acumatica Licensing Guide dated April 2024 lists web API requests per minute at the top consumption tier as 50 on Essentials, 100 on Select, 150 on Prime and 300 on Enterprise, with maximum concurrent API connections of 10, 10, 20 and unlimited, and it states that when connections exceed the maximum the system prevents additional users from logging in. A storefront making a runtime price call per product on a category page can consume that budget quickly, which is an argument for caching rather than an argument against runtime pricing.
Is caching prices dangerous?
Less dangerous than showing the wrong customer the wrong number, which is what a fallback to list price does. The real questions are how long a cached contract price may be served and what invalidates it, and both are commercial decisions rather than technical ones. Most distributors are comfortable honouring a price that is a few hours old and extremely uncomfortable showing a contract customer list price, so write down the maximum age and have the person who owns pricing agree it.
Does going headless or composable make this better or worse?
Neither by itself. What changes the answer is how many independent calls a page makes before it can render, because every one of those is a thing that can fail slowly. A decoupled front end that reads from its own read model degrades well; one that fans out to three services per page view degrades badly. Judge an architecture by how many failure points sit between a buyer and a price, not by the label on the diagram.

Last updated 2026-08-20. Facts on this page last checked against source 2026-08-20.