security · 6 min read

UUID versions — v4, v7, and which to use

Thirty-two hex digits that two machines can generate independently and never collide. The interesting part is what the newest version fixed.

A universally unique identifier is 128 bits, written as thirty-two hexadecimal digits in five dash-separated groups. The point is that anything can generate one at any time without coordinating with anything else, and the result will not clash.

That property is what makes distributed systems possible without a central counter — and it is also what made them awkward as database keys, until v7.

The versions worth knowing

v4 — random. 122 random bits, six reserved for version and variant markers. The default nearly everywhere, and the right answer when you want an identifier that reveals nothing.

v7 — time-ordered random. The first 48 bits are a millisecond timestamp; the rest is random. Standardised in 2024 and now the recommended choice for anything that becomes a primary key.

v5 — derived from a name. Hashes a namespace and a string, so the same input always produces the same identifier. Useful for deterministic ids from natural keys, and not random at all.

v1 — timestamp and MAC address. The original. It embeds the generating machine's network address, which is a disclosure nobody intends, and it is worth avoiding for that reason alone.

Why v4 is hard on a database

This is the practical argument and it is not obvious.

A database index is ordered. Inserting a row with an auto-incrementing integer always appends at the end, so the same page stays in memory and writes are cheap.

Random identifiers land everywhere. Each insert touches a different page, the working set becomes the whole index rather than its tail, pages split repeatedly, and the index fragments. On a large table this is the difference between a fast write and a slow one.

v7 restores the ordering. Identifiers generated close together in time sort close together, so inserts cluster at the end again — while keeping the independence that made UUIDs worth having.

Collisions, honestly

122 random bits is about 5.3 × 1036 possibilities. To reach a one-in-a-billion chance of a single collision you need to generate roughly 2.7 × 1018 of them.

At a million per second that is around eighty-five thousand years. The probability is negligible against every other failure mode in the system.

The real risk is not mathematics but a weak random source. A UUID generated from a poorly seeded generator — an embedded device at first boot, a virtual machine cloned from a snapshot — can repeat, and that has happened. The guarantee comes from the randomness, not from the format.

As a secret

A v4 UUID from a cryptographic source is unguessable, and using one as a password-reset link or an unlisted share URL is reasonable.

v1 and v7 are not, and this is worth being clear about. Both embed a timestamp, so anyone who knows roughly when a token was issued has eliminated most of the search space. v1 additionally publishes the MAC address of the machine that made it.

So the version that is best as a database key is the wrong one for a secret. Use v7 for rows and v4 — or a purpose-built random string — for anything that has to be unguessable.

Storing them

As text a UUID is 36 characters. As bytes it is 16, so a native UUID column is worth using where the database has one — less than half the storage, and every index entry smaller.

Where there is no native type, 16 raw bytes beats a 36-character string, at the cost of being unreadable in a query result.

The short version

v4 by default, v7 for anything that becomes a primary key, v5 when the same input must always give the same identifier, and not v1. Collisions are not a real concern; a weak random source is. And a v7 is a poor secret, because half of it is the clock.

Questions

What is the difference between UUID v4 and v7?

v4 is entirely random. v7 puts a millisecond timestamp in the first 48 bits and fills the rest with randomness, so generated identifiers sort in creation order. Both are effectively collision-proof; v7 is much kinder to a database index.

Can two UUIDs be the same?

In principle yes, in practice no. A v4 UUID has 122 random bits, and you would need to generate about 2.7 × 10^18 of them before a collision reached even a one-in-a-billion chance. The risk is far below that of the hardware failing.

Why is UUID v7 better for database keys?

Random identifiers scatter inserts across the whole index, so every write touches a different page and the index fragments. v7 is time-ordered, so new rows land together at the end — the same property that made auto-incrementing integers fast, without a central counter.

Are UUIDs secure to use as tokens?

A v4 UUID from a cryptographic random source is unguessable and fine as an unguessable identifier. v1 and v7 are not — v1 embeds a MAC address and a timestamp, and v7 embeds a timestamp, so both leak information and are partly predictable.

How many UUID versions are there?

Eight are defined. Four matter: v1 time and MAC based, v4 random, v5 derived deterministically from a name, and v7 time-ordered random. v4 remains the common default and v7 is the one worth switching to for database keys.

Tools from this guide