Tools › Guides › UUID versions compared: v4, v7, v1 and v5

UUID versions compared: v4, v7, v1 and v5

Which UUID version to use, why v4 is a poor database key, and what v7 fixed. With the one case where a random ID is exactly wrong.

The short version

database primary key.

for database keys.

A different tool for a different problem.

v4: random, and almost always fine

122 random bits. The chance of two ever colliding is small enough that you can stop thinking about it: you would need to generate a billion a second for about 85 years to reach a 50% chance of a single duplicate.

It is the right default because it needs no coordination. Two machines that have never spoken can both generate IDs and never collide, which is the whole point of a UUID.

Why v4 is a poor primary key

This is the practical thing worth knowing, and it surprises people.

Databases store rows in an index ordered by the primary key. With a sequential key, each new row lands at the end of the index: the page it belongs on is already in memory and it stays there. With a random key, every insert lands in a random place in the index, which means reading a different page from disk every time and splitting pages constantly.

On a large table the difference is not subtle. Inserts get slower as the table grows, the index fragments, and the working set stops fitting in memory because every page is touched equally.

MySQL with InnoDB is hit hardest because the table is physically ordered by the primary key. PostgreSQL suffers less but still suffers.

v7: the fix

v7 puts a millisecond timestamp in the leading 48 bits and fills the rest with randomness. The result is still a UUID, still collision-resistant, still generated without coordination, but two IDs made a second apart sort in the order they were made.

That restores the sequential insert pattern, and it gives you something else for free: you can sort by ID and get chronological order, without a separate created-at column in the index.

It is the right choice for any new table using UUID keys. It became a published standard in 2024, and support is now broad.

The trade: a v7 UUID leaks roughly when it was created. If your IDs are public and creation time is sensitive, that matters.

v1: what v7 replaced

v1 also encodes a timestamp, but with the bytes in an order that does not sort lexically, and with the machine's MAC address in the low bits. That address identifies the hardware that generated it: a genuine privacy consideration that got v1 quietly dropped from a lot of systems.

Use it when something else requires it. Otherwise v7.

v5: the one that is not random at all

v5 is a hash. Give it a namespace and a name, and it returns the same UUID every time, on every machine, for ever.

That is useful in a specific and recurring situation: you need a stable ID for something that already has a natural identifier, and you want any two systems to independently agree on it without talking.

`` namespace: URL name: https://example.com/products/1234 ``

Both services derive the same UUID. No lookup table, no coordination, no sync. The classic uses are content addressing, deduplication, and mapping external keys into an internal ID space.

The standard namespaces are DNS, URL, OID and X.500, or you can generate a v4 once and use it as your own namespace for ever.

Note that v5 is not a secret. Anyone who knows the namespace and the name can compute the ID, so it must never be used as a capability or a password.

(v3 is the same idea using MD5 instead of SHA-1. There is no reason to prefer it.)

Nil

00000000-0000-0000-0000-000000000000. It means "no UUID" in a column that cannot be null. It is a sentinel, and treating it as an identifier is a bug waiting to be found.

Format notes

The canonical form is 36 characters, lowercase, with hyphens. Uppercase is valid and comparing case-sensitively is a common source of bugs.

Stored as text it costs 36 bytes; stored as a native uuid or binary(16) column it costs 16. On a table with hundreds of millions of rows and a few indexes, that difference is measured in gigabytes.