codebench_TOOL: HomeLOCAL-ONLY⌘K Switch

UUID v4 vs v7: Which Should You Use for Database Keys?

UUID v4 is random; UUID v7 is time-ordered. Learn how each is built, why v4 fragments B-tree indexes, and when v7 is the better primary key.

·3 min read

For years, "use a UUID" meant version 4: 122 random bits formatted as 36 hex characters. Version 7, standardized in RFC 9562 (2024), keeps the same shape but front-loads a timestamp. The difference sounds minor and turns out to matter a great deal for database performance.

The common format

Every UUID is 128 bits, displayed as 8-4-4-4-12 hex groups:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
  • M is the version nibble: 4 for v4, 7 for v7.
  • N encodes the variant; for both versions it is one of 8, 9, a, or b.

Everything else depends on the version.

UUID v4: pure randomness

f47ac10b-58cc-4372-a567-0e02b2c3d479

Apart from the 6 fixed bits (version and variant), all 122 bits come from a cryptographically secure random source. Two properties follow:

  • Collision is a non-issue. You would need to generate about 2.7 × 10¹⁸ UUIDs to have a 50% chance of a single duplicate.
  • There is no order. Two v4 UUIDs generated a microsecond apart are unrelated. Sorting them is meaningless.

Generate a few with the UUID v4 Generator and notice that nothing about them changes over time.

UUID v7: time first, then randomness

0191f7a8-3c2e-7d5b-9e4f-1a2b3c4d5e6f
│          │
└── 48-bit Unix timestamp (ms)

The layout is:

Bits Content
48 Unix timestamp in milliseconds
4 Version (7)
12 Random, or a sub-millisecond counter
2 Variant
62 Random

Because the timestamp occupies the most significant bits, v7 UUIDs sort by creation time when compared as strings or as 128-bit integers. Generate several in a row with the UUID v7 Generator and the first characters march upward.

The 48-bit millisecond field lasts until the year 10889, so overflow is not a practical concern.

Why ordering matters for databases

Most relational databases store primary keys in a B-tree. Inserting a row means finding the right leaf page and writing the key there.

With v4, every new key lands at a random position. Over time this causes:

  • Page splits throughout the tree rather than only at the right edge.
  • Poor cache locality — recently inserted rows are scattered across the whole index, so the working set is effectively the entire index.
  • Fragmentation that inflates index size and slows range scans.

With v7, new keys are always larger than existing ones, so inserts append to the rightmost page — the same access pattern as an auto-increment integer. Benchmarks on PostgreSQL and MySQL routinely show v7 inserts running noticeably faster than v4 at scale, with smaller indexes.

A secondary benefit: ORDER BY id gives you insertion order for free, and you can approximate a created_at range query on the key alone.

What v7 gives away

The timestamp is readable by anyone who sees the ID. From a v7 UUID you can tell roughly when the row was created, and from two of them, which came first. For many systems that is harmless. For some — say, invoice numbers exposed in a URL, where you would rather not leak issuance rate — it is information you did not intend to share.

v4 leaks nothing. If IDs are public and creation time is sensitive, that is a point in v4's favor.

What about v1?

Version 1 was the original time-based UUID. It also embeds a timestamp, but in a scrambled byte order that does not sort naturally, and it includes the generating machine's MAC address. The UUID v1 Generator exists for compatibility with older systems; for new work, v7 does everything v1 did without the drawbacks.

Recommendation

Situation Use
Primary key in a relational database v7
Sort or partition by creation time v7
ID is public and creation time is sensitive v4
Need an ID with no information content at all v4
Interoperating with a system that expects v1 v1

For the default case — a primary key that nobody outside the system sees — v7 is the better choice. It keeps the global uniqueness of v4 while restoring the insert locality of a sequence.

Summary

  • v4 is 122 random bits with no order; v7 is a 48-bit millisecond timestamp followed by random bits.
  • Random keys fragment B-tree indexes; time-ordered keys append, which is faster and smaller.
  • v7 reveals creation time. Choose v4 when that matters.
  • Both are drop-in replacements for each other at the storage level: same 128 bits, same string format.
#uuid#database#identifiers
codebench $Ctrl+Enter Run