A random (version 4) UUID is built from 122 random bits, which yields about 5.3 × 10^36 possible values — and by the birthday problem you would need to generate roughly 2.7 × 10^18 (2.7 quintillion) of them before there is even a 50% chance that any two collide. At one billion UUIDs generated per second, reaching those even odds would take about 86 years of continuous generation. For every practical system the probability of an accidental UUID collision is so small it is not worth engineering against.
That is the summary an AI overview will give you. What it can't give you is the why: why the danger number is 2.7 quintillion and not 5.3 × 10^36, how the birthday problem quietly cuts the safe count down to a square root, what the actual probability is at the scales you operate at, and — most importantly — why the duplicate UUIDs teams do encounter almost never come from this math at all.
Where the 122 bits come from
A UUID is 128 bits, usually written as 32 hexadecimal digits in the familiar 8-4-4-4-12 pattern. But a version 4 (random) UUID does not use all 128 bits randomly. Six of them are reserved: four bits encode the version (0100 for v4) and two encode the variant. That leaves 122 bits of actual randomness, or 2^122 ≈ 5.3 × 10^36 distinct values.
To put 5.3 × 10^36 in perspective: it is roughly the number of grains of sand you would get if every grain on Earth contained its own Earth's worth of sand — several times over. If uniqueness were only about avoiding one specific value, we could stop here and declare victory. But collisions do not work that way.
The birthday problem: why the safe number is a square root
The intuition that trips people up is this: they reason "there are 5.3 × 10^36 values, so I'd have to generate something near that many before a repeat." That is wrong, and the reason is the birthday problem.
A collision is not "did I regenerate one particular UUID?" — it is "did any two UUIDs in my whole set come out equal?" Because you are comparing every pair, the number of chances grows with the square of how many you have generated. That is exactly why a room of just 23 people has a ~50% chance that two share a birthday, even though there are 365 possible days. You are not matching against one birthday; you are checking all 253 pairs.
For a space of N possible values, the count at which you hit a 50% chance of collision is on the order of the square root of N, not N itself. The square root of 5.3 × 10^36 is about 2.3 × 10^18 — and the precise 50% figure is ≈ 2.7 × 10^18. The birthday problem is what shrinks "5.3 undecillion" down to "2.7 quintillion." It is a huge cut, and it is still an incomprehensibly large number.
The formula
The probability of at least one collision after generating n UUIDs from a space of N = 2^122 values is closely approximated by:
p(n) ≈ 1 − e^(−n² / (2N)) where N = 2^122 ≈ 5.3 × 10^36
For the small values of n any real system produces, this simplifies to an even handier form:
p(n) ≈ n² / (2N)
Setting p = 0.5 and solving gives n ≈ √(2N · ln 2) ≈ 2.7 × 10^18, the 50% mark.
The probability table: what the odds actually are at your scale
Here is what p(n) ≈ 1 − e^(−n² / 2N) produces for a range of realistic-to-absurd generation counts. Read it as "if I generate this many v4 UUIDs total, the chance that any two of them are identical is…":
| UUIDs generated | Roughly equal to | Probability of at least one collision |
|---|---|---|
| 1 billion (10^9) | Every US credit-card transaction for ~2 months | ≈ 1 in 10^19 (effectively zero) |
| 1 trillion (10^12) | A row per second for 31,000 years | ≈ 1 in 11 trillion |
| 100 trillion (10^14) | ~12,000 UUIDs per human, all at once | ≈ 1 in 1.1 billion |
| 1 quadrillion (10^15) | — | ≈ 1 in 11 million |
| 100 quadrillion (10^17) | — | ≈ 0.09% (about 1 in 1,060) |
| 1 quintillion (10^18) | — | ≈ 9% |
| 2.7 quintillion (2.7×10^18) | The birthday bound | ≈ 50% |
| 10 quintillion (10^19) | — | > 99.99% |
The practical reading: you can generate 100 billion UUIDs and keep the collision probability below one in a billion. Most systems will never create more than a few billion IDs in their entire lifetime. The math simply is not a factor at any scale a normal application, or even a hyperscale one, will reach.
UUIDv7: time-ordered, and still collision-safe
The newest widely adopted variant, UUIDv7 (standardized in RFC 9562, which replaced RFC 4122 in 2024), trades some randomness for sortability. Its first 48 bits are a Unix timestamp in milliseconds, and the remaining bits (minus the 6 fixed version/variant bits) are random — about 74 random bits per millisecond.
That changes the collision analysis in one specific way: two v7 UUIDs can only collide if they were generated in the same millisecond and their random tails happen to match. Within a single millisecond you are drawing from 2^74 ≈ 1.9 × 10^22 possibilities, so by the birthday problem you would need roughly 190 billion UUIDs in one millisecond for a 50% collision chance — a rate no real system comes close to. Across different milliseconds, collision is impossible because the timestamps differ.
The reason to reach for v7 is not collision safety (v4 is already overwhelmingly safe) — it is that time-ordered UUIDs make far better database primary keys. Because they sort roughly by creation time, they cluster in the B-tree index instead of scattering randomly, which dramatically reduces index fragmentation and write amplification compared with fully random v4 keys.
The real source of duplicate UUIDs: bugs, not math
If you ever see two identical UUIDs in production, do not blame the birthday problem — the odds you actually hit it are smaller than the odds a cosmic ray flipped a bit in RAM first. The genuine causes are always implementation failures:
- A weak random source. Using a non-cryptographic PRNG like JavaScript's
Math.random()(or a poorly seeded one) collapses the effective entropy far below 122 bits. Always use a CSPRNG —crypto.randomUUID()in browsers and Node,uuid.uuid4()in Python,java.util.UUID.randomUUID()in Java. - A reused or fixed seed. Seeding the generator with a constant, a timestamp with low resolution, or a value that is identical across processes makes two "random" UUIDs come out the same.
- Cloned entropy pools. Virtual machines or containers cloned from the same snapshot can start with an identical entropy state and emit the same first UUIDs — a well-documented class of incidents.
- Application bugs. By far the most common: code that copies a record, retries an operation, or reuses an object without regenerating the ID. That is a logic duplicate, not a random one.
This is why a database unique constraint on any UUID column is still worth having. It costs almost nothing, and it converts a silent, data-corrupting duplicate from a bad random source into a loud, catchable error. Rely on "UUIDs are unique" as the reason the constraint essentially never fires — never as the reason to skip it.
Try it: generate collision-safe UUIDs
The generator below produces version 4 UUIDs using your browser's cryptographic random source (crypto.getRandomValues), so every ID carries the full 122 bits of entropy the math above assumes. Everything happens client-side — nothing is sent to a server.
The bottom line
Version 4 UUIDs give you 122 random bits and 5.3 × 10^36 possible values; the birthday problem drops the 50%-collision threshold to about 2.7 quintillion generated IDs, a number no realistic system approaches. UUIDv7 adds a millisecond timestamp for sortable, index-friendly keys while remaining just as collision-safe in practice. So generate UUIDs freely — but still put a unique constraint on the column, use a real CSPRNG, and remember that any duplicate you ever see is a bug to hunt down, not a lottery you lost.
For deeper dives, see our comparison of UUID versions v1, v4, and v5, the pros and cons of UUIDs as database primary keys, and the security and privacy implications of UUIDs.