A listing tool sends new items to a marketplace. Some time after an item is created, the marketplace issues a warehouse ID for it, and the tool needs that ID on its own row. The tool got it there in one way only: the seller's batch page asked for it and saved it. When the seller closed the page early, nobody asked, and the ID was never saved.
Key facts
- The batch page polled the marketplace for each new item's warehouse ID and wrote it back. It stopped asking after 3 hours.
- 684 of 2,699 new rows (25.3%) never got the ID.
- The fix moved the write to the server, into the consumer that already reads the marketplace's inventory notifications.
- After the change, 0 of 114 rows were missing an ID the marketplace had issued. 2 were still waiting on the marketplace.
- One row filled in the same second its notice arrived, 80 minutes after the item was created. The consumer logged 95 fills in its first 4 hours.
What happened
After a seller sent a batch, the page kept asking the marketplace, every few seconds, whether each new item had a warehouse ID yet. When an answer came back with one, the page wrote it to the item's row. To keep the page from asking forever, the polling stopped after 3 hours.
That loop was the only thing in the whole system that finished the record. Nothing on the server ever asked. So the ID got saved only if the seller kept the page open until the marketplace issued it, and only if that happened within 3 hours. Sellers who sent a batch and moved on, which is a normal thing to do, left their rows without an ID for good.
Why it hid
Anyone who watched a batch saw it work. The IDs appeared one by one, right there on the page. Testing it meant keeping the page open, so every test passed.
The loss fell only on people who were not looking, and people who are not looking do not report what they did not see. The rows without an ID looked like rows still waiting, not like rows that would wait forever.
The fix
The server already had a consumer that reads the marketplace's inventory notifications. Those notices carry the warehouse ID once it exists. The fix moved the write there: when a notice carries the ID, the consumer fills every matching row. The page still shows the ID, but now it only reads it.
Before
After
The first hours showed the change. One row filled in the same second its notice arrived, 80 minutes after the item was created. The consumer logged 95 fills in its first 4 hours.
A fill you can run twice
Events arrive late, twice, or out of order. The fill has to be safe in all three cases. Three rules make it so:
- Fill only where empty. A value already there is never overwritten, so a repeated or stale notice does no harm.
- Match on the stable key. Use the key both sides agree on and that never changes, not a name or a position in a list.
- Log one count line. How many rows each notice filled. That line is how you know it works, and how you notice when it stops.
on inventoryNotice(n):
if not n.warehouseId: return
filled = update items
set warehouseId = n.warehouseId
where key = n.key
and warehouseId is empty
log("warehouse id fill", n.key, filled)
Run it twice and the second run fills 0 rows. That is the point.
How to find these spots
Look for writes that live inside page polling. Search the client code for timers and polling loops (setInterval, setTimeout chains, refetch intervals, effects that start a timer), then look inside them for a save, an update, a POST or a mutation. Each one you find is a record that a screen finishes.
Then look for limits on those loops: a time cap, a retry count, a "stop after N tries". A cap is a sign that someone expected the loop to give up, and every give-up is a record left unfinished.
How to measure the loss
Count the share of records missing the field, compared with the source of truth. The useful number is not "rows with no ID". It is "rows where the source has a value and we do not". Rows the source has not issued yet are waiting, not lost.
Here that was 684 of 2,699 new rows, 25.3%. After the fix the same count gave 0 of 114, with 2 rows still waiting on the marketplace. Run the count again a few days after any fix, so you can see the gap stay closed.
The general rule
This is not about warehouse IDs. Any app where a browser tab or a mobile screen is the thing that finishes a record has the same hole: polling for a status, an ID, a payment result, or the output of an AI job. People close tabs, lock phones and lose signal.
The rule is short. The page may show the result sooner, but the server must save it, from the event or from a server-side poll when there is no event. The save must not depend on anyone looking.
Common questions
What if the source sends no events?
Run a poll or a sweep on the server instead, on a schedule, with the same fill: only where empty, matched on the stable key. It is slower than an event, but it does not need anyone to be looking.
Can I keep the page poll?
Yes, to show the value sooner. It must not be the only thing that saves it. If the page also writes, give it the same empty-only fill, so the two writers can never undo each other.
What about rows created before the fix?
Run the same fill once over the old rows, using the source of truth, then count again. What is still missing should be only the rows the source has not issued yet.
Melta is free; join the waitlist.