10. Unique ID Generation
10.4 What are UUIDs, and which version should you use?
The options
At the bank: Instead of a token machine, every customer draws a raffle ticket with a very long number. No machine and no coordination; the number is so long that two people drawing the same one is practically impossible.
In the system: A UUID (universally unique identifier) is a 128-bit value, usually written as 32 hex digits in groups: 019b76da-a800-7c0c-a13b-d2ff2ed057ee. Any server can create one on its own, with no coordination. The current standard (RFC 9562) defines several versions; two matter for system design.
Figure: v4 is all randomness; v7 puts the time first; Snowflake packs time, machine and a counter into 64 bits.
10.4.1 UUID v4 (random)
At the bank: The pure raffle ticket: random, tells you nothing.
In the system: 122 of the 128 bits are random (the other 6 mark the version and variant).
- No coordination, unguessable.
- Collisions are practically impossible: you'd need to create about 2.7 × 10¹⁸ v4 UUIDs before the chance of even one duplicate reached 50%. Creating a trillion gives a chance of about 1 in 10 trillion.
- Downsides: 16 bytes instead of 8; and they're randomly ordered. As a primary key in a B-tree (Chapter 9), each new row lands in a random place in the index, so inserts touch pages all over the index instead of just the end. On big tables that means more page splits, more cache misses and slower writes.
10.4.2 UUID v7 (time-ordered)
At the bank: A raffle ticket whose first digits are the time it was drawn, followed by random digits.
In the system: The first 48 bits are the Unix time in milliseconds; the rest is mostly random.
- Sorts by creation time, so new rows go near the end of the index, like auto-increment.
- Still needs no coordination and has plenty of randomness (74 bits) against collisions.
- The trade-off: anyone can read the creation time out of the ID. Usually fine; occasionally sensitive.
For new systems that want UUIDs, prefer v7 over v4 for database keys. Many languages and databases now generate it directly (Python 3.14's standard library, for example, has uuid.uuid7()).
Memory code: "v4 is a raffle ticket; v7 is a raffle ticket with a timestamp on the front."