UUID v4 vs v7: Which Should You Use for Database IDs?
UUID v7 puts a timestamp at the front so IDs sort in creation order. Here is how v4 and v7 differ, what that means for database indexes, and when random v4 is still the right choice.
formvoxo Team
Developer Relations
Try it as you read
Generate v4 and v7 UUIDs side by side, and decode the timestamp inside a v7. No login.
For years "use a UUID" meant UUID v4: 122 random bits that never collide. It works, but random keys have a cost inside databases. UUID v7, standardised in RFC 9562 in 2024, fixes that by putting a timestamp at the front. Here is what actually differs and how to choose.
What the two look like
v4 9f1c2e7a-3b4d-4c8e-a1f2-6d7e8f9a0b1c
v7 019a2b3c-4d5e-7f60-8a1b-2c3d4e5f6a7b
└──────────┘ └ version digit
48-bit Unix time in milliseconds
Both are 128 bits, use the same 8-4-4-4-12 text format and fit in the same uuid column. The 13th character is the version: 4 or 7. In a v4, everything else is random. In a v7, the first 12 hex digits are the creation time, followed by random bits.
Why random keys hurt database indexes
Most databases store a primary key in a B-tree index, kept in sorted order. Auto-increment IDs always go at the end of that index, so new rows fill one page after another and recently written pages stay in memory.
A random v4 key belongs at a random place in the sorted order. Every insert touches a different page of the index, pages split half-full, the index grows larger than it needs to be, and the working set no longer fits in memory. On big tables this shows up as slower inserts and much heavier disk use. MySQL with InnoDB feels it most, because the table itself is stored in primary key order.
A v7 key starts with the current time, so new keys are always larger than old ones, just like an auto-increment. Inserts append to the end of the index again, while you keep the benefits of UUIDs: you can create IDs in the browser or on many servers without asking the database, and they do not reveal how many records you have.
Side by side
- Sorting: v7 sorts by creation time, so
ORDER BY idmeans "oldest first". v4 has no order. - Index performance: v7 behaves like an auto-increment. v4 scatters writes across the index.
- Uniqueness: both are safe in practice. v4 has 122 random bits, v7 has 74 per millisecond.
- Privacy: v7 reveals when a record was created, to the millisecond. v4 reveals nothing.
- Support: v4 is everywhere. v7 is in PostgreSQL 18, recent versions of every major language and most ORMs.
When v4 is still the right choice
Because a v7 contains its creation time, anyone who sees the ID learns when the record was made. That is usually harmless for an order or a log entry, but not for everything:
- Password reset links, invite codes and API keys: use random tokens (v4 or longer), never v7.
- Public IDs where timing is sensitive, for example when an account or a medical record was created.
- Values used purely as random secrets. For those, a dedicated random token is better than any UUID.
A common pattern is v7 as the internal primary key and a separate random token for anything that ends up in a public URL.
How to generate each
// JavaScript: v4 built in; v7 via the "uuid" package
crypto.randomUUID();
import { v7 } from 'uuid'; v7();
# Python 3.14+
import uuid
uuid.uuid4(); uuid.uuid7()
// PHP / Laravel
Str::uuid(); Str::uuid7();
-- PostgreSQL 18
SELECT gen_random_uuid(); -- v4
SELECT uuidv7(); -- v7
If your stack does not have v7 yet, the format is simple: 48 bits of Date.now(), then the version and variant bits, then random bytes. The UUID generator builds them exactly like that in your browser, and its decoder shows the timestamp inside any v7.
Storing UUIDs
- PostgreSQL: use the native
uuidtype (16 bytes), nottext(36+ bytes). - MySQL: store as
BINARY(16)withUUID_TO_BIN(), orCHAR(36)if simplicity matters more than size. - Everywhere: store lowercase and compare case-insensitively, since some tools print UUIDs in uppercase.
The short answer
For new tables with UUID primary keys, choose v7. Keep v4, or a dedicated random token, for anything public that should not reveal when it was created. If you collect data through forms, formvoxo already gives every submission its own ID in the dashboard and in webhook payloads, so you can store it next to your own UUID keys.
Share this article