Skip to content

2026-08-05 · 7 min read

UUID v4 vs v7: randomness, indexes, and when to switch

A practical comparison of UUID v4 and UUID v7 for primary keys, sort order, privacy of timestamps, and database index locality.

What a UUID actually is

A UUID is 128 bits with a version nibble that says how those bits were constructed. The canonical string is 32 hex digits and four hyphens (36 characters). RFC 9562 updates the older RFC 4122 layouts and standardizes v7. UUIDs are identifiers, not capabilities. Anyone who can guess or enumerate them should not gain access; if they do, you built a secret into an ID. Generate them with a CSPRNG (Web Crypto, `crypto.randomUUID`, `/dev/urandom`), never with `Math.random()`.

v4: random and scattered

v4 fills most bits with random data. Collision risk is negligible at application scale (122 bits of randomness). The downside is index locality: new rows insert at random positions in a B-tree, which can page-split and bloat indexes on hot tables. v4 is still a good public ID when you do not want the identifier to reveal creation time. It is a poor default for a primary key on a write-heavy OLTP table if you have a time-ordered alternative.

v7: time-ordered without v1’s baggage

v7 puts a Unix timestamp in the high bits and random data in the rest. Values roughly sort by creation time, so inserts append near the end of an index. That is usually what you want for primary keys. You do leak an approximate creation timestamp to anyone who sees the ID. If that is a problem (for example, hiding when an account was created), keep v7 internal and expose a random public slug. Do not use v1 in new work: legacy layouts could embed MAC addresses. ULID occupies a similar niche; v7 is the UUID-shaped version that fits existing UUID columns.

NanoID, keys, and prefixes

Public IDs in URLs are often nicer as NanoIDs or base32 strings than as hyphenated UUIDs. Keep them long enough for your collision budget. API keys should look different from row IDs: a prefix (`dk_live_`) plus a high-entropy tail, shown once, stored as SHA-256 on the server. PureDevKit’s generator can emit v4, v7, NanoID, and custom alphabets entirely in the browser so fixture seeds never pass through a hosted API.

Related tools