Section 5: Sixty-Four Bits and Almost Nothing Else - Data Modeling: The ID Layout & Coordination State
Executive Summary: In most designs, data modeling means tables. Here, the main data model is the ID itself: 64 bits whose layout decides how records sort, how indexes grow and what downstream teams can safely do with the value. We decode Leo's ID field by field with shifts and masks, explain why the timestamp sits in the high bits (sorting by ID approximates sorting by time, and inserts append to the right edge of a B-tree instead of landing at random like UUIDv4), and then model the system's stored state. That state is tiny: one static region number per region and a handful of etcd keys per worker. There is no database of issued IDs, and we show why keeping one would be absurd. The section ends with a warning for consumers: the same high time bits that make IDs sort well make them a bad range shard key.
The interviewer looks at the API from Section 4 and asks the usual question: "So what's the schema?" Instead of reaching for a database, pick up the marker and draw a 64-bit box.
You: "This system is unusual. Most of the 'data' is the ID itself, and the layout is the schema every team in the company will inherit. The stored state is small enough that I can list every key. Let me take the ID first."
The ID Is the Data Model
Section 3 sized each field by asking one question per field. Here is the result:
| Bits | Field | Range | Question it answers |
|---|---|---|---|
| 1 | Sign | Always 0 | Is it a positive BIGINT? (Yes, always.) |
| 41 | Timestamp | ms since 2026-01-01T00:00:00Z, about 69.7 years | When was it minted? |
| 3 | Region | 0–7 (5 in use) | Which region minted it? |
| 7 | Worker | 0–127 per region | Which generator inside that region? |
| 12 | Sequence | 0–4,095 | Which ID within that worker's millisecond? |
Now take Leo's message. He sends "boarding now ✈️" from Lisbon at 2026-10-15 09:30:00.123 UTC. The messaging service in eu-west (region 2) asks worker 17, which has already minted 5 IDs in that millisecond, so the sequence is 5.
Building it is three shifts and three ORs:
ms since epoch = 287 days × 86,400,000 + 34,200,000 + 123 = 24,831,000,123
id = (24,831,000,123 << 22) // timestamp above the 22 low bits
| (2 << 19) // region above worker + sequence
| (17 << 12) // worker above sequence
| 5 // sequence
= 104148763141017605 // hex 0x017202BF8ED11005, 57 significant bits
Decoding is the same thing in reverse, which is exactly what Section 4's Decode endpoint does:
timestamp = id >> 22 = 24,831,000,123 → add the 2026-01-01 epoch → 09:30:00.123 UTC
region = (id >> 19) & 0x7 = 2 → eu-west
worker = (id >> 12) & 0x7F = 17
sequence = id & 0xFFF = 5
The next ID worker 17 mints in that same millisecond is 104148763141017606. Only the sequence changed, so only the last digit moved.
Interviewer: "Your ID has 18 decimal digits. Anything that bites downstream?"
You: "Yes. It's bigger than 2^53, which is 9,007,199,254,740,992, so a JavaScript client parsing it as a JSON number silently rounds it to a different ID. That's why Section 4's HTTP gateway returns it as a string. In the database it's a plain signed BIGINT, and because the sign bit is always 0, signed and unsigned order agree."
Quick check before moving on:
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson