A date is not a timestamp
Lab note · 2026-08-05 · Reserve — an AI-native studio.
Our company brain wakes up once a day, reads a table of recurring jobs, and runs the ones that are due. The table has one column that does all the work: last-run, a bare date. 2026-08-04. The rule is as simple as it looks — a daily job is due unless last-run is already today.
Two founders, two laptops, two timezones. That is the entire bug.
The machine in the earlier timezone crosses midnight hours before the other one does. For those hours it reads a table whose cells say 2026-08-04, checks its own calendar, sees 2026-08-05, and concludes — correctly, by the stated rule — that every daily job is due. It is not confused about the date. It is not confused about the rule. It applies the rule perfectly and gets the wrong answer, because the rule was written by someone who had only ever run it in one place.
The failure is worse than a duplicate. If the early machine runs the jobs and writes 2026-08-05 into the cells, the machine that was supposed to run them wakes up hours later, reads its own freshly-claimed row, and skips. The work does not get done twice. It gets done once, by the wrong machine, and then not at all by the right one. We have a six-day stretch in our logs from an earlier variant of exactly this — a daily report that silently stopped going out because something upstream kept claiming it had already gone out.
What makes this worth writing down is that nothing in the system was broken. Every component did what it was told. The bug lived in a type: we stored a date where the semantics required an instant. A date is a local, observer-relative label. A timestamp is a point that every observer agrees on. They render almost identically — 2026-08-04 and 2026-08-04T16:15Z sit next to each other in a table looking like the same kind of thing — and the difference only surfaces when a second observer shows up. Which, in a two-person company, happened on roughly the first day we had a second person.
The general shape: any value that coordinates two parties has to be expressed in terms both parties can evaluate identically. A local date fails that test. So does “today,” “this week,” “the latest version,” and every other phrase whose referent depends on who is asking. Distributed systems people have known this forever; the interesting part is that we did not build a distributed system. We built a checklist in a markdown table. The property snuck in the moment a teammate cloned the repo.
There are three fixes and only one of them is real. You can tell people to run the job on one machine — a social fix that decays. You can add a guard that refuses to claim a cell that looks suspiciously early — a patch that treats the symptom. Or you can change the type: store the instant, compare instants, and let each machine render it however it likes locally. The first two keep the ambiguity and manage it. The third deletes it. We have been running on the first for weeks, which is how we ended up with a heartbeat that is correct on one continent.
← All lab notes