Build

Let''s Handle State — Touch the Value, Not the Screen

By makemind · Jan 23, 2026

Two weeks ago the number board sat at 41. The buttons named tools, and the tools didn't exist.

Now they get wired. But before wiring, one thing has to be decided — who holds that number.

Why this is a question

If the screen holds it, the code is short. Press the button, a value inside the screen goes up by one, the screen redraws. The server doesn't need to know.

And the day you add a second panel, it's over. One at the waiting-room door, one beside the counter. Each counts its own, so the two show different numbers. The customer reads the one in front of them and the staff reads the one beside them.

The number does not belong to the screen. It belongs to the counter.

The counter holds it

So the state lives on the server side.

var _now = 41;
var _issued = 41;

now is the number being called, issued is the last ticket handed out.

Two tools touch them.

server.addTool(
  name: 'queue.next',
  description: 'Call the next number',
  inputSchema: const {'type': 'object', 'properties': {}},
  handler: (args) async {
    // The counter refuses to pass the last ticket it issued. Without this
    // the display runs ahead of the room and calls numbers nobody holds.
    if (_now >= _issued) return _state(notice: 'nobody is waiting');
    _now++;
    return _state(notice: 'called $_now');
  },
);

Start with the refusal

The first thing checked after wiring was not the case that works, but the case that shouldn't.

Nobody is waiting, and "Call next" gets pressed.

pressed Call next -> now 41 ("nobody is waiting")
the counter refused: it will not call past the last ticket issued

It stayed at 41. Without that check the display runs ahead of the room — it calls 42 that nobody holds, then 43, and when the real holder of 42 walks up it has already gone past.

Now it moves

Three tickets are taken.

three tickets taken -> issued 44, 3 waiting
NOW SERVING 41 — 3 waiting · issued 44
NOW SERVING 41 — 3 waiting · issued 44

Two are called.

called twice -> now 43, 1 waiting
NOW SERVING 43 — 1 waiting · issued 44
NOW SERVING 43 — 1 waiting · issued 44

43, one left. 41 + 2 = 43, 44 − 43 = 1. The screen didn't compute that; the counter did and sent it.

There is no 41 and no +1 anywhere in the screen. Only the slots {{now}} and {{waiting}}.

Unplug it and plug it back in

This is the most important part of this piece.

Number boards get unplugged. Power fails, panels get swapped, someone cleaning catches the cable. What happens then is unknowable unless you check.

So the connection was dropped and a different display attached.

display disconnected — the server process ends with it
a different display connects
it reads 43/44 before, 41/41 after
NOW SERVING 41 — 0 waiting · issued 41
NOW SERVING 41 — 0 waiting · issued 41

Back to 41. The waiting count is 0 too.

This isn't a bug; it's a fact about how this sample is actually made. The state lives in the server process's memory, and the display is attached over stdio, so when the display dies the server process dies with it. The queue went with the process.

the number did NOT survive: this counter keeps its queue in memory,
so the process ending took the queue with it

This content requires Developer or above

Sign in and upgrade your plan to continue reading.

View Plans
Twitter