Comparison

UUID v4 vs v7

A v4 UUID is entirely random; a v7 UUID puts a millisecond timestamp in its leading bits and fills the rest with randomness. Both are practically unique. The difference is ordering: v7 values sort by creation time, which keeps database index writes sequential. Use v7 for database primary keys and v4 where the value must reveal nothing.

UUID Generator

Generate random v4 or time-ordered v7 UUIDs in bulk.

Open the tool

For twenty years v4 was the default answer, and for most purposes it was the right one: 122 random bits, no coordination needed, collisions not worth worrying about. The problem only shows up at the storage layer.

Because v4 values are random, consecutive inserts land in unrelated places in a B-tree index. That scatters writes across pages, fragments the index and hurts cache locality. Version 7, standardised in RFC 9562 in 2024, fixes it by making the leading bits a timestamp so new values sort to the end.

What actually differs

  • Structure: v4 is 122 random bits; v7 is a 48-bit millisecond timestamp followed by 74 random bits.
  • Ordering: v7 values sort by creation time as strings and as bytes. v4 values have no order.
  • Index behaviour: v7 appends to the end of a B-tree; v4 inserts randomly throughout it.
  • Information leaked: v7 reveals when the identifier was created, to the millisecond. v4 reveals nothing.
  • Uniqueness: both are safe in practice. v7 keeps 74 random bits per millisecond, which is ample.
  • Support: v4 is available everywhere. v7 needs a recent library or a short helper function.

Why random primary keys hurt

A B-tree index keeps its entries in order. Sequential keys append to the rightmost page, which stays in memory and fills neatly. Random keys write to arbitrary pages, so each insert may pull a different page into memory and leave pages part-full. On a large table this shows up as slower writes, a larger index, and worse cache behaviour. It is the single strongest argument for v7.

When v4 is still right

Whenever the identifier is visible and the creation time should not be. A v7 identifier in a public URL tells anyone who reads it exactly when the record was made — which can expose signup times, order volumes or how new an account is. For password reset tokens, session identifiers, share links and anything security-adjacent, use v4, or better a purpose-built random token.

What about v1 and v5?

Version 1 also encodes a timestamp but its byte order does not sort correctly, and it traditionally embedded the machine's MAC address — a privacy problem that made it fall out of favour. Version 7 is its modern replacement. Version 5 is different in kind: it hashes a namespace and a name with SHA-1, so the same input always produces the same identifier. That is what you want for deterministic IDs derived from existing data, and it is not interchangeable with either.

Choosing

Use v7 for database primary keys and anything where insert performance or natural ordering matters. Use v4 for public-facing identifiers where the creation time is sensitive. Use v5 when the identifier must be reproducible from its inputs. If you are storing them, store as a native UUID or 16-byte binary column rather than a 36-character string — the text form roughly doubles the storage and the index size.

Frequently asked questions

Are v7 UUIDs less unique than v4?
In principle yes — 74 random bits rather than 122 — and in practice it makes no difference. Within any given millisecond you would need to generate an implausible number of identifiers before a collision became worth considering.
Does v7 leak information?
It reveals its creation time to the millisecond, which is fine for an internal primary key and can matter for a public one. An identifier in a URL would tell anyone exactly when the record was created.
Should I migrate existing v4 keys to v7?
Rarely worth it on its own. The index benefit applies to new inserts, and rewriting primary keys means updating every foreign key that references them. Use v7 for new tables and leave working ones alone.
Is v7 widely supported yet?
It was standardised in RFC 9562 in May 2024 and support is now common in current library versions across most languages, with database-native functions arriving more gradually. Generating one is a short function if your stack lacks it.
What about ULIDs?
A ULID solves the same problem — a timestamp prefix plus randomness — and predates v7. The practical difference is that v7 is a standard UUID, so it fits existing UUID columns, types and tooling. For new work, v7 is the more portable choice.

Tools used in this guide

All tools →
All guides →

Last reviewed .