UUID Versions and Collision Risk
A UUID looks like a random string, but its version encodes strategy — randomness, time-ordering, or host identity. Choosing the right version is a design decision; understanding the collision math is what keeps you from over-engineering around it.
Updated 2026-08-06 · ~7 min read
What a UUID actually guarantees
A UUID is a 128-bit identifier designed for generation without coordination: no central registry, no collision check, just an algorithm whose output space is astronomically large. The guarantee is probabilistic, not absolute — collision is possible but engineered to be negligible. The mental model that matters: UUIDs trade a certainty nobody can provide in distributed systems for a probability so small that storage designs can ignore it. Everything else follows from that trade.
The collision math, honestly
Version 4 UUIDs carry 122 random bits. The birthday-bound calculation says a 50 percent collision chance requires generating around 2.71 times 10 to the 18 of them — billions per second for decades. Concrete scale: a system minting one million UUIDs per day would need roughly seven trillion years of operation for a 50 percent chance of one collision. This is why production systems skip global uniqueness checks: the engineering cost of the check exceeds the expected cost of the event, which is effectively zero.
Version 4: the randomness default
V4 fills the bits with randomness — no time, no host, no sequence. That anonymity is a feature: the ID leaks nothing about when or where it was generated. It is also the weakness for databases: random keys scatter inserts across index pages, degrading write performance at scale. For application identifiers, session tokens, and anywhere volume is moderate, v4 remains the right default precisely because it carries no metadata to leak.
Version 7: time-ordered for databases
V7 embeds a millisecond timestamp in the leading bits, so IDs sort by creation time. The practical wins: index locality (inserts append rather than scatter), free rough ordering without a created_at column lookup, and human-debuggable timestamps recoverable from the ID itself. The trade: generation time leaks by design, which matters if the ID is public and the timing is sensitive. Modern databases and ORMs increasingly default to v7 for primary keys for exactly these performance reasons.
The format: hyphens, case, and normalization
Standard rendering is 8-4-4-4-12 hex groups hyphenated — 32 hex digits plus four hyphens. Two version bits and a variant field live at fixed positions, which is how tooling identifies v4 versus v7 by inspection. Storage questions recur: store as hyphenated strings for readability or as raw 16 bytes for compactness — either works, but mixing representations across systems invites comparison bugs. Normalize (lowercase, consistent hyphenation) before comparing UUIDs across sources.
When NOT to use UUIDs
UUIDs are not always right. Sequential integers remain better for public pagination URLs (shorter, sortable, leak volume — sometimes that is acceptable). Human-facing references (ticket numbers, order codes) want short memorable formats, not 36-character strings. And any context where the ID is typed by hand favors shorter schemes. The rule: UUIDs solve uniqueness without coordination; where coordination exists or readability dominates, simpler formats win.
Testing fixtures and development uses
The daily uses outside production schemas: test data needing unique keys across runs, correlation IDs for tracing a request through services, idempotency keys preventing double-submission, and cache-busting parameters. Each use exploits a different property — uniqueness across generators for fixtures, randomness for correlation, uniqueness-per-operation for idempotency. Generating a batch at once covers the fixture case; one per operation covers the others.
Idempotency keys: the underrated pattern
Payment and submission APIs use client-generated UUIDs as idempotency keys: retry the same request with the same key, and the server recognizes it as a retry rather than a new action. The pattern converts network unreliability from double-charges into safe retries. The discipline is per-operation uniqueness — a new key per intended action, reused across retries of that action. Getting this backwards (new key per retry) defeats the protection entirely.
Local generation for keys that seed sensitive systems
Identifiers sometimes seed sensitive contexts before any server exists. Browser-side generation produces them with nothing transmitted — the UUID forms locally from the platform's randomness source. For the everyday cases (fixtures, correlation IDs, one-off keys), local generation is simply the fastest path with the fewest moving parts.
Version 1 and the privacy history of MAC-address IDs
The original UUID version embedded the generating machine's MAC address plus a timestamp — uniqueness guaranteed by hardware identity, at the cost of leaking where and when an ID was created. That embedded hardware address became a tracking concern, which is the historical reason randomness-based v4 took over and why v7 replaces the node field with random bits while keeping the timestamp. Reading older systems that generate v1 UUIDs is a reminder that identifier formats encode policy decisions; when you find MAC-based IDs in a modern stack, migrating to v4 or v7 removes the leakage without any uniqueness cost.
Short IDs and when abbreviation is acceptable
Thirty-six characters is hostile in user-facing contexts, which is why teams reach for shorter formats: truncated UUIDs, base62 encodings, application prefixes. The trade is always entropy: a 12-character base62 ID carries roughly 71 bits — fine for collision tolerance at moderate scale, inadequate for unguessable security tokens. The honest framework: compute the bits the shortened form actually carries, compare against what the use case needs (collision tolerance versus unpredictability), and document the choice. Abbreviating UUIDs for display while storing the full value is the safe middle: humans see the short form, systems keep the real one.
Choosing a UUID version deliberately
UUIDs differ by version and the differences are operational, not cosmetic. Version 4 — random — is the default choice for identifiers: 122 bits of randomness makes collisions a non-issue at any earthly scale, and it leaks nothing about when or where it was created. Version 1 and 6 embed a timestamp and MAC address, which is why they sort chronologically but also fingerprint the generating machine — a privacy property most applications do not want. Version 7, the newer design, combines a millisecond timestamp prefix with random bits: still effectively collision-free, but now naturally sortable by creation time.
Sortability is the decision point that separates v4 from v7 in practice. Databases index random keys poorly: every insert lands on a random B-tree page, splitting pages constantly and fragmenting the index. For primary keys in high-write databases, time-ordered UUIDv7 (or sequential alternatives) measurably reduces write amplification. For tokens, session ids, correlation ids, and anything not stored as a primary key, v4's randomness is an advantage rather than a cost, because predictability is an attack surface you do not need.
Two format notes prevent recurring bugs. The canonical form is 32 hex digits in 8-4-4-4-12 groups, lowercase by convention — store one form consistently, since string comparison is case-sensitive in most languages. And UUIDs are not secrets: they are identifiers, often logged and exposed in URLs. Anything granting access needs separate unguessable credentials, not a hard-to-guess UUID.
Common mistakes with this tool
- Worrying about UUID collisions and adding unnecessary uniqueness checks.
- Using v4 primary keys in high-write databases where v7's ordering pays.
- Comparing UUIDs without normalizing case and hyphenation.
- Reusing idempotency keys across distinct operations.
Frequently asked questions
Can two UUIDs be the same?
Possible in theory, negligible in practice — v4 collision needs around 10 to the 18 generations for a 50 percent chance.
What is the difference between UUID v4 and v7?
V4 is pure randomness; v7 embeds a millisecond timestamp so IDs sort by creation time and index better in databases.
Should I store UUIDs with hyphens?
Either works — pick one representation and normalize before comparing across systems.
Are UUIDs random enough for security tokens?
V4 uses strong randomness, but purpose-built token generation with explicit entropy budgets is the better practice.
Is generation safe for sensitive projects?
Yes — UUIDs form locally in your browser; nothing is transmitted.
Can two UUIDs ever collide?
With version 4, the probability is real but absurdly small — you would need to generate billions per second for years to approach it. For all practical systems, collisions can be treated as impossible.
Should I use UUIDv4 or UUIDv7 for database keys?
v7 for primary keys in high-write databases: its timestamp prefix keeps inserts sequential, which indexes handle much better. v4 for everything that is not a hot index key.