DEV Community

zhihu wu
zhihu wu

Posted on

UUIDv7 vs UUIDv4: Why Time-Sortable IDs Are Winning (and When v4 Is Still Right)

If you have ever used a random UUID as a database primary key and watched writes slow down as the table grew, it was not your imagination — and the fix became an official standard back in May 2024.

The problem with random keys

A UUID v4 is 122 bits of pure randomness. Insert a few million rows and every new row lands at a random position in your B-tree index. The database keeps splitting pages and evicting cache lines, and your writes pay for it. On write-heavy tables this fragmentation is a real, measurable cost.

What UUIDv7 changes

UUIDv7 keeps the familiar 128-bit shape but replaces the first 48 bits with a Unix timestamp in milliseconds. The remaining bits are still random. Because IDs generated close together are close in value, new rows append near the end of the index instead of poking holes in the middle. B-tree locality improves, page splits drop, and you get a free bonus: rows are roughly sortable by creation time, which makes "latest first" queries and cursor pagination noticeably cheaper.

Adoption is already here

  • Python 3.14 added uuid.uuid7() to the standard library
  • The uuid npm package ships uuidv7() (v11+)
  • Go's google/uuid has NewV7()
  • Postgres has the pg_uuidv7 extension, and built-in support keeps spreading

The trade-offs you should know

UUIDv7 leaks timing information — the timestamp is right there in the ID. That is fine for database keys but wrong for security tokens, session IDs, or anything where you do not want to reveal when a record was created. Use v4 or a dedicated random token there.

Also, "time-sortable" is best-effort, not a guarantee: if one process generates IDs in a tight loop, or a machine clock rolls back, ordering can drift. For most backends that is noise; for strict event ordering you need a sequence, not a UUID.

When v4 is still the right call

If your table is read-heavy or sits under roughly ten million rows, v4 is perfectly fine — the index overhead is negligible compared with the simplicity. v4 is also what crypto.randomUUID() in browsers and Node.js produces today, and it works everywhere with zero new tooling. Do not migrate an existing happy system just to chase v7.

Try it yourself

When I need a UUID in the middle of debugging, I use a free client-side generator at CodeToolbox — everything runs in the browser, nothing is uploaded, and the page includes a quick v4 vs v7 vs ULID comparison if you want the full picture before choosing an ID strategy for your next project.

Top comments (0)