UUIDv7 vs UUIDv4 as a Primary Key: What Actually Changes

Both are 128-bit UUIDs. The only structural difference is where the random bits go — and that one difference is why UUIDv7 is increasingly recommended over UUIDv4 for database primary keys.

The bit layout is the whole story

UUIDv4 (RFC 4122) is 122 bits of randomness plus a 6-bit version/variant marker. Every UUIDv4 is unpredictable and unordered by construction — there is nothing to sort by except insertion order tracked elsewhere.

UUIDv7 (RFC 9562 §5.7) replaces the first 48 bits with a Unix millisecond timestamp, keeps a 4-bit version nibble and 2-bit variant, and fills the remaining 74 bits with randomness. That's the entire difference:

FieldUUIDv4UUIDv7
Bits 0–47randomUnix ms timestamp
Bits 48–51 (version nibble)01000111
Bits 52–127random (minus 2 variant bits)random (minus 2 variant bits)
Sortable by creation timenoyes, to millisecond resolution
Total random bits12274

Why this matters for a primary key specifically

A B-tree primary-key index wants keys that arrive in roughly ascending order. A fully random UUIDv4 key inserts at a random point in the index on every single row, which fragments the index page layout and defeats the sequential-write pattern most storage engines are tuned for — the well-documented "random UUID primary key" cost in Postgres, MySQL/InnoDB, and similar B-tree-indexed engines. A UUIDv7 key inserts at (almost) the end of the index every time, the same access pattern as an auto-incrementing integer, while still being globally unique and generatable client-side without a round trip to ask the database for the next value.

This is a storage-engine/index-locality effect, not a correctness one: both UUIDv4 and UUIDv7 are valid, unique 128-bit identifiers. The tradeoff is purely about how the index behaves under sustained insert load, and about whether "when was this row created" is a question the ID itself can answer.

The tradeoff: timestamps are no longer hidden

A UUIDv7 leaks its creation time to anyone who can read the raw ID — a user, an API caller, a log line. If exposing "when exactly was this record created" (down to the millisecond) to whoever holds the ID is unacceptable for a given field (e.g. a security token, an ID handed to an untrusted client where creation-time correlation is a real information leak), UUIDv4 is still the right choice. For most primary keys — rows, orders, sessions internal to a system — this tradeoff favors UUIDv7.

See it decoded

Paste any UUID below: if it's a v7, the decoder extracts the embedded millisecond timestamp and shows the exact creation date. If it's a v4 (or any other version), it tells you there's no meaningful timestamp to extract, since the first bits are just randomness.

→ Open the UUIDv7 & ULID decoder