The Cloudflare Stack · Part 1 of 1
Why Durable Objects Replaced Our Polling Loop
- cloudflare
- durable-objects
- alloresto

AlloResto’s live order board is the one screen every kitchen actually watches. It has to be right, and it has to be right now — not eventually consistent, not “refresh in a few seconds.”
The coordination problem
Early on, order state lived in Postgres and every tablet on the floor polled it. That worked until a location had more than a couple of screens open: two expo tablets marking the same ticket “ready” within the same second would race on the update, and whichever write landed second silently won — sometimes flipping a ready order back to “in progress.” Tightening the polling interval just moved the collision window around; it didn’t close it. Row-level locking closed it but added latency to the one interaction that couldn’t afford any.
The actual problem wasn’t the database. It was that “who owns this order’s state” had no single answer — any tablet, any request, any region could write to it at any time.
Giving every location a coordinator
We put a Durable Object in front of order state, keyed one-per-restaurant-location. Every ticket update for a given kitchen routes through env.ORDER_BOARD.getByName(locationId) and lands on the same object every time.
That single fact removes the race entirely — a Durable Object processes one request at a time, so “mark ready” and “mark ready” from two tablets serialize instead of colliding. State lives in the object’s own SQLite storage, so there’s no round trip to a separate database on the hot path. And because the board needs to push updates the moment they happen, every connected tablet holds a hibernatable WebSocket to its location’s object, so the update fans out without any device polling at all.
What we didn’t get for free
Picking the right shard key mattered more than we expected. One object per location is the right grain — coarse enough that a busy dinner service isn’t fighting for a single global lock, fine enough that a slow write in one kitchen never touches another. We still run a periodic alarm per object for the boring stuff — closing out stale tickets, nightly reconciliation with the reporting pipeline — because coordination and scheduled cleanup turned out to be the same primitive.
The database didn’t fail us. We just never had a good answer for who was in charge until every location got its own.