UUID v4 or v7: Why You Should Adopt Sortable IDs in 2026
v7 carries a timestamp and maintains compatibility. When to switch, how to migrate, and what changes in database indexes.
If you still use SERIAL as primary key on high-write tables, this post is for you. But even if you've already migrated to UUID v4, there's a pragmatic reason to consider v7 now — and it has to do with database indexes, not RFC bureaucracy.
The problem with UUID v4 in indexes
UUID v4 is completely random. This means each INSERT into a table with a B-tree index on the UUID needs to insert the key at a random position in the tree. With sufficient write volume, this causes severe fragmentation and hot pages in the index — the database constantly reads and writes pages that aren't in cache.
On low-volume tables, you won't notice. On tables with millions of inserts per day, this shows up in response time and disk I/O.
What UUID v7 solves
UUID v7 (RFC 9562, published in 2024) embeds a 48-bit timestamp in the first bytes of the UUID. This guarantees that UUIDs generated close in time are close in the index. Sequential inserts in time → sequential inserts in the index → no fragmentation.
UUID v4 (random):
4a8e12f3-b7c1-4d2e-9f3a-1c5e8b2d7f9a
UUID v7 (timestamp + random):
01960000-0000-7xxx-xxxx-xxxxxxxxxxxx
└─ timestamp ─┘ └──── random ────┘
The random part still exists — ensuring uniqueness even with multiple simultaneous generators. The difference is that the time part comes first.
Compatibility
UUID v7 is a valid UUID in the standard 36-char format. UUID columns in PostgreSQL, MySQL, and SQLite accept v7 without any changes. ORMs that treat UUIDs as opaque strings also work without modification.
What changes is only the generator. In Node.js:
import { uuidv7 } from 'uuidv7';
const id = uuidv7(); // '01960b2a-4f7e-7d3c-8f1a-2c4e6b8d0f2a'
In Python:
import uuid_utils
id = str(uuid_utils.uuid7())
When NOT to migrate
- If your table has fewer than ~100k inserts per day, the gain is marginal
- If you already use ULID (which solves the same problem differently), there's no reason to migrate
- If UUIDs are publicly exposed and you need them to be completely opaque — v7 leaks timing information (approximately when the record was created)
Migrating from v4 to v7
You don't need to migrate existing IDs. You just need to swap the generator. New IDs will be v7, old IDs remain v4. The index will improve gradually as new records dominate the distribution.
To generate and inspect UUIDs of any version, the Quick Tools UUID Generator supports v4 and v7 with visualization of the embedded timestamp.
Use v7, period.
How to adopt UUID v7 with low risk
The safest migration is to swap only the generator for new records. You don't need to rewrite old IDs or change the column type if it already accepts standard UUID. The database starts receiving new time-orderable IDs, while old records remain valid.
Before changing, confirm whether any part of the system assumes UUIDs are completely random. Logs, auditing, and integrations rarely care, but systems that treat timing as sensitive information may prefer v4. UUID v7 reveals approximately when the ID was created.
Migration checklist
Test ordering, indexes, and serialization in all services that generate IDs. Also check fixtures, mocks, and frontend validations. Some older regexes accept any UUID, but others may hardcode version 4 in the third group.
After deploying, monitor index fragmentation, insert time, and index size over the following weeks. The gain appears gradually as new IDs come to represent a larger portion of the table.
Use the UUID Generator to compare v4 and v7 side by side and explain the change to the team before updating the official generator.
How to explain it to the team
The best way to sell UUID v7 isn't to cite the RFC, but to show the operational effect: more index-friendly inserts and IDs still compatible with the UUID type. When the team understands that the change is local to the generator, adoption stops feeling like a risky migration.
Decision point
UUID v7 makes more sense when the table grows continuously and the ID participates in a primary index or operational ordering. If the system is small, the change can wait. If volume is high, switching early avoids more expensive optimizations later.
- 01 UTF-8 and encoding problems: why accents break and how to fix them What UTF-8 is, code points, mojibake, and why accented text turns to garbage — the mechanism explained end to end.
- 02 MIT, Apache, and GPL Licenses: Practical Differences for Developers MIT, Apache 2.0, and GPL are not the same thing. Understand permissive vs copyleft, patent protection, and compatibility before shipping code to production.