OpenToolkit
ProductivityDeveloperGuides

Could Two UUIDs Ever Collide? The Strange Mathematics of Almost-Impossible IDs

Two computers can invent IDs without coordinating and almost never choose the same one. Explore the birthday paradox, UUID collision odds, hidden failure modes, and what robust systems do anyway.

UUID strings floating between independent databases while two matching identifiers approach a collision point

Imagine two databases on opposite sides of the world. They are offline, cannot ask a central server for the next available number, and both need to create millions of records. Months later, their data will be merged. How can they name every record now without accidentally choosing the same identifier?

A UUID is one answer. It lets each machine create an identifier independently, with no shared counter and no advance reservation. That sounds like a loophole in logic: if nobody checks which numbers have already been taken, a duplicate must eventually appear. It can—and the mathematics behind when it becomes plausible is much stranger than simply counting the available IDs.

The short answer

Two properly generated UUIDs can be identical, but a collision between random version-4 UUIDs is extraordinarily unlikely at ordinary scale. UUIDv4 has 122 random bits, giving 2122, or about 5.3 undecillion, possible random values. The remaining six bits identify the UUID version and variant.

The important catch is that collision risk does not become serious only after every possible value is used. Because every new UUID can match any earlier UUID, the number of possible pairs grows quickly. This is the same idea behind the birthday paradox.

Why a 128-bit UUID has only 122 random bits

A familiar UUID is written as 32 hexadecimal characters separated into five groups:

c0a8012e-7d63-4d52-9b95-2a670ebf2d89

That text represents 128 bits, but not all 128 bits are free to vary in UUIDv4. Four bits record the version, so the first character in the third group is always 4. Two more bits record the standard variant, so the first character in the fourth group is one of 8, 9, a, or b. The current UUID standard, RFC 9562, assigns the other 122 bits to random or pseudorandom data.

You can see the pattern rather than take it on faith. Open the OpenToolkit UUID Generator, create a batch of UUIDv4 values, and compare those two positions. The tool uses the browser's secure crypto.randomUUID() API, generates up to 1,000 values at once, and does not send the results to a server.

The birthday paradox enters the database

In a room of only 23 people, there is already a better-than-even chance that two share a birthday, assuming 365 equally likely birthdays. The room does not need 366 people because we are not asking whether anyone matches one particular birthday. We are checking every person against every other person.

UUID collisions work the same way. With n generated IDs, there are roughly n squared divided by two pairs that could collide. When n is much smaller than the number of possible values N, a useful approximation is:

collision probability ≈ n² / (2N)

For UUIDv4, N is 2122. The square root of that enormous space—not its full size—is therefore the scale that matters. A 50% chance of at least one collision arrives at roughly 2.7 quintillion generated UUIDs.

What do those odds feel like at real speeds?

The 50% threshold sounds less abstract when converted into generation rates:

  • At one million UUIDs every second without stopping, reaching 2.7 quintillion UUIDs would take about 86,000 years.

  • At one billion UUIDs every second, it would still take about 86 years to reach the 50% threshold.

  • After generating one trillion UUIDs, the approximate collision probability is 9.4 × 10−14—about one chance in 10.6 trillion.

  • After generating one quadrillion UUIDs, the probability rises to about one chance in 10.6 million.

These figures assume uniformly random, independent UUIDv4 generation across the whole collection. They do not mean a specific UUID is “safe for 86 years,” and they do not predict the moment a duplicate must occur. Probability permits an early collision; it merely makes one fantastically unlikely.

The practical danger is usually not the mathematics

When duplicate identifiers appear in a real system, suspect the generator or the surrounding code before blaming the 122-bit address space. The theoretical calculation assumes randomness that implementations do not always deliver.

A weak or predictable random source

A UUID-shaped string is not automatically a well-generated UUID. Code based on a small seed, a basic pseudo-random function, or repeated timestamps may explore only a tiny corner of the available space. Millions of visually different-looking possibilities are still dangerously few for a large distributed system.

In browsers, the Web Cryptography specification defines crypto.randomUUID() as a UUIDv4 generator backed by cryptographically secure random bytes. Use a reputable operating-system, runtime, or database UUID function instead of assembling UUIDs with Math.random().

Cloned system state

Virtual machines, containers, embedded devices, or test environments can be copied from the same snapshot. A badly designed generator may restart from identical state on every clone and emit identical sequences. Good system randomness is designed to avoid this, but custom generators can accidentally recreate the problem UUIDs were meant to solve.

Truncating the identifier

Teams sometimes remove characters to make UUIDs more attractive in URLs or support tickets. That is not cosmetic. Every hexadecimal character removed discards four bits and divides the remaining space by 16. A 12-character hexadecimal ID has only 48 bits; its 50% collision point is around 20 million values, not quintillions.

If compact text matters, change the encoding instead of throwing entropy away. Removing hyphens or switching letter case keeps the same UUID value. Cropping characters does not.

A copy, retry, or import bug

Duplicate records may reuse an existing ID because an application object was copied, a retry replayed a request, or an import mapped the wrong column. In those cases the generator never collided. The application assigned the same already-generated value twice.

Why databases should still enforce uniqueness

“Astronomically unlikely” is not a data-integrity rule. A UUID column used as a primary key or public identity should have a primary-key or unique constraint. If generation genuinely collides, the write fails cleanly and the application can generate a new value and retry. The same constraint also catches mundane programming mistakes.

A robust pattern is simple:

  1. Generate the UUID with a secure, standard implementation.

  2. Insert it into a column protected by a unique constraint.

  3. If the database reports a duplicate-key error, investigate and retry with a new UUID when appropriate.

  4. Monitor repeated collisions, because more than one is evidence of a system fault, not spectacular bad luck.

This is defense in depth: probability makes collisions rare; the constraint makes them harmless.

UUIDv4 is not the only interesting version

The version digit changes what the identifier means. UUIDv1 includes a timestamp and historically incorporates a node identifier, which can create privacy concerns. UUIDv3 and UUIDv5 are deterministic: the same namespace and name produce the same UUID, using MD5 and SHA-1 respectively. They are useful when repeatability—not fresh randomness—is the goal.

UUIDv7, standardized in RFC 9562, puts a Unix timestamp in the most significant 48 bits and uses the remaining available fields for random data or monotonic sequencing. Because newer values generally sort after older ones, UUIDv7 can behave more naturally in database indexes than completely random UUIDv4 values. That ordering also leaks approximate creation time, which may be undesirable for public identifiers.

The choice is therefore not merely “unique or not.” It includes questions about sort order, privacy, deterministic generation, runtime support, and how much independence distributed writers require.

A UUID is an identifier, not a secret

Randomness can make a UUID difficult to guess, but possession of an identifier must not be treated as authorization. If changing the UUID in an API URL exposes another user's document, the access-control design is broken—even if guessing a valid value is unlikely.

Do not use UUIDs as passwords, session secrets, or proof that a request is trusted. Use proper authentication, authorization checks, and purpose-built cryptographic tokens. If you are examining a structured authentication token, the JWT Decoder can reveal its readable header and payload locally, but decoding a token does not verify its signature.

Try a small UUID experiment

Generate 100 values with the free browser-based UUID generator, then paste them into a text editor. A few properties are easy to inspect:

  1. Every UUID contains 32 hexadecimal characters; hyphens only improve readability.

  2. The first character of the third group is 4, identifying UUIDv4.

  3. The first character of the fourth group is 8, 9, a, or b, identifying the RFC variant.

  4. Uppercase and lowercase versions represent the same hexadecimal value.

You almost certainly will not observe a collision. More importantly, the exercise shows that “random” does not mean every character is unconstrained. A UUID is a structured 128-bit value with carefully reserved fields.

Questions that reveal the hidden edge cases

Can two companies generate the same UUID?

Yes in theory. UUID generation does not reserve a private range for each company. With secure UUIDv4 generators, all participants draw from the same enormous space, and the combined collision probability remains negligible at normal scale.

Does removing hyphens increase collision risk?

No. Hyphens are formatting characters and carry no entropy. A UUID with or without hyphens represents the same 128-bit value. Removing hexadecimal characters, however, shortens the identifier and sharply increases risk.

Can a UUID reveal when it was created?

It depends on the version. UUIDv1 and UUIDv7 contain time information. UUIDv4 is random and does not encode a creation timestamp, although surrounding application data, sequential database records, logs, or URLs may still reveal timing.

Should every project switch from integer IDs to UUIDs?

No. Auto-incrementing integers are compact, naturally ordered, and perfectly suitable when one database coordinates all writes. UUIDs become particularly valuable when IDs must be generated before insertion, records come from multiple independent systems, or public identifiers should not expose a simple sequence.

The real trick is coordination without communication

The most remarkable property of a UUID is not that its number is large. It is that millions of machines can make local decisions that remain compatible when their data finally meets. No central ticket dispenser has to stay online, and no network round trip is required before an object can have a stable name.

The birthday paradox explains why the usable scale is closer to the square root of the space, while 122 random bits make even that square root enormous. Secure generation supplies the probability; database constraints supply the guarantee; careful system design prevents ordinary bugs from masquerading as impossible coincidences.