jonnifyelixir
F4 / F4.07 / choosing

F4.07 · part 1 of 3

Choosing an identifier

The first id scheme anyone reaches for is a database counter: 1, 2, 3. It sorts by time and it is tiny, but it needs one writer to hand out the next number, so it does not survive being split across machines. The reaction is a random UUID: any node can mint one with no coordination — but it is 128 bits and sorting a pile of them tells you nothing about when they were made. A Snowflake keeps the good half of each: coordination-free like a UUID, time-sortable like a counter.

Three ids from each scheme, created in the order shown. Sort them as plain strings and see which schemes recover the original order — the property that lets a database paginate by id.

Does sorting recover time order?

A list paginated “by id” only works if id order is time order. Pick a scheme: the left column is three ids in the order they were created; the right column is the same three sorted as plain strings. When the two columns match, the scheme is time-sortable.

Id scheme · select one

created (oldest first) sorted as strings — — — → — — — — sorting these ids recovers the order they were made in

      

role: a central counter

result: sorted == created

A counter and a Snowflake both sort back into creation order; a random UUID does not. The Snowflake reaches that without a single shared writer, which is the trait the counter could not keep.

Advanced: the three tradeoffs

Three properties decide an id scheme. Coordination: a counter needs exactly one writer to stay unique, so it caps you at one node; a UUID and a Snowflake do not. Order: sorting must recover creation time for id-based pagination and range scans; a counter and a Snowflake have it, a random UUID does not. Size: a UUID is 128 bits, a Snowflake 64, a counter fewer still — and 64 bits is one machine word, which a database indexes and compares cheaply.

A Snowflake is the scheme that holds all three at once: coordination-free because each worker owns its own sequence, ordered because the timestamp sits in the high bits, and 64-bit because the three fields are packed tight. That is why the portal mints Snowflakes rather than auto-increment ids or UUIDs — and why the next dive takes the 64 bits apart.

# the same three records, three ways to name them
counter   = [1001, 1002, 1003]            # ordered, but one writer only
uuid_v4   = ["f47ac10b…", "0e8400e2…", …]  # no coordination, not ordered
snowflake = [318710061465600000, …]      # ordered AND coordination-free

counter · UUID

Each keeps one of order or coordination, and gives up the other.

F4.07.2 · the Snowflake

Packs a timestamp, a worker, and a sequence into 64 bits to keep both.

Next: the Snowflake bigint — how 64 bits split into a timestamp, a worker id, and a sequence, and how shifts and masks read them.

References

Primary sources for this lesson, and where it connects in the course.

Sources

Related in this course