Storefronts and marketplaces
Stop the last unit being sold twice
One stock room, two shop fronts. The store and the marketplace each believe they hold the last unit, and both sell it. Events alone will not hold the two in step, because a missed or repeated event moves a number that cannot be moved back. What keeps them honest is a timer that re-reads both sides and a write that refuses to land on a count it did not expect.
- Triggers
- Two
- Runs
- Every 10 minutes
- Stack
- 4 tools
- Durable execution
- Required
The flow
The top track records what the sale did. The bottom track re-reads both sides on a timer and writes only when they disagree.
An order comes in
Shopify Admin API
Work out the new count
n8n · Make
Write the stock ledger
Sheets · Airtable
Every 10 minutes
n8n 排程
Read both sides
n8n
Counts disagree?
n8n IF
Set the count, with a compare
Shopify Admin API
Leave it alone
—
Step by step
- 01
An order comes in
Shopify Admin APIA webhook fires on the sale. Treat it as a hint that something moved, not as the number itself.
- 02
Work out the new count
n8n · MakeDeduct against the count you last read, and key the run on the order id. A decrement that fires twice cannot be undone by firing it again — this is the step that has to survive a mid-run crash, which is why durable execution is not optional here.
- 03
Write the stock ledger
Sheets · AirtableOne row per movement, with the order id. The ledger, not either shop front, is what you reconcile against when the two disagree.
- 04
Every 10 minutes
n8n 排程The reconciliation pass. It runs whether or not any webhook arrived, which is the point — a webhook that never lands leaves no trace to notice.
- 05
Read both sides
n8nPull the live count from the store and from the marketplace, and the last figure in the ledger.
- 06
Counts disagree?
n8n IFCompare all three. Anything other than agreement means a movement was missed, duplicated, or applied out of order.
- 07
Set the count, with a compare
Shopify Admin APIWrite an absolute quantity and pass the value you expect to find. If somebody sold in the seconds since you read, the write fails instead of overwriting the sale.
What the platform will not allow
The design above is not a preference. Each part of it exists because of a documented behaviour on Shopify's side.
inventorySetQuantities sets an absolute quantity and takes a compareQuantity — the write only lands if the persisted value still matches. Shopify's own note on skipping that check: it "can lead to inaccurate inventory quantities if multiple requests are made concurrently".
Shopify Admin GraphQL API — inventorySetQuantitiesWebhook delivery "isn't always guaranteed", and Shopify "doesn't guarantee ordering within a topic, or across different topics for the same resource". The documentation's own remedy is a reconciliation job that periodically re-fetches the data — which is the bottom track of this flow.
Shopify — About webhooks (best practices)Shopify allows one second to connect and five seconds for the whole request. With no response it retries eight times over four hours, and after eight consecutive failures a subscription created through the Admin API is deleted automatically — so a webhook endpoint that is down over a weekend can come back with no subscription at all.
Shopify — Deliver webhooks through HTTPSThe GraphQL Admin API is metered by calculated query cost, not request count: 100 points per second on standard plans, and no single query may exceed 1,000 points. A sweep that reads every SKU at once will hit the ceiling before it hits a request limit.
Shopify — API rate limits
When this is not worth building
Three cases where the upkeep costs more than the oversells.
You sell made-to-order, or hold enough depth that the last unit is never contested. The whole flow exists for the final unit; without that pressure it is machinery guarding nothing.
The two channels do not share a stock room. If each has its own allocation, they are not out of step — they are separate businesses, and forcing one number on them creates the conflict it was meant to prevent.
Nobody owns the correction. When the sweep finds drift, someone has to decide whether the ledger or the shop front is right. Without that person the workflow writes a number every ten minutes and nobody knows which way the error runs.