UUIDv4 vs UUIDv7: Why Time-Ordered IDs Make Better Database Keys
A UUID is a 128-bit identifier that two systems can generate independently and still never collide, which makes it ideal for primary keys, event ids, and anything that needs to be unique without a central counter. For years the default was UUIDv4, which is purely random. Since 2024 there is a better option for databases, UUIDv7, and the difference comes down to one word: order. Generate either version with the UUID Generator, in your browser.
Try the UUID Generator toolGenerate 5 random RFC 4122 version 4 UUIDs at once. The input is ignored; run again for a new batch.Two versions, one big difference
Both versions are 128 bits and look identical at a glance, the familiar 8-4-4-4-12 string of hex digits. What differs is how the bits are chosen. UUIDv4 fills almost all of them with random data, so two ids created a millisecond apart are completely unrelated. UUIDv7 puts a 48-bit Unix timestamp, in milliseconds, into the most significant bits and fills the rest with randomness. That means UUIDv7 values created in sequence sort in roughly the order they were made, while UUIDv4 values are scattered with no order at all. Both were standardised together in RFC 9562, published in May 2024.
| UUIDv4 | UUIDv7 | |
|---|---|---|
| Content | Random | Timestamp (ms) plus random |
| Ordered by creation time? | No | Yes |
| Reveals when it was made? | No | Yes, roughly |
| Best for | Public ids, unguessable tokens | Database primary keys |
Why random UUIDs hurt databases
Most databases store a table's primary key in a B-tree index, which keeps entries sorted. When new keys arrive in order, each one is added at the end, near the last one, so the database touches the same few pages and keeps them in memory. That is what an auto-incrementing integer gives you for free.
A random UUIDv4 destroys that pattern. Each insert lands at a random spot in the index, forcing the database to read and modify a different page almost every time. Pages fill unevenly and split, parent pages are rewritten, and the set of pages the database must keep in memory balloons. At small scale you will not notice. At large scale, benchmarks repeatedly show random-UUID inserts running several times slower than ordered ones, sometimes by an order of magnitude, purely because of this lost locality.
What UUIDv7 fixes
Because a UUIDv7 starts with a timestamp, ids generated close together in time are close together in the index too. New rows append near the most recent ones instead of scattering, so page splits drop, cache hit rates climb, and insert throughput rises to something close to an integer key, while keeping the collision-free, generate-anywhere property that made you choose a UUID in the first place. Support is now landing in the databases themselves: PostgreSQL 18, for example, ships a built-in function to generate UUIDv7 values directly.
The catch: UUIDv7 leaks time
This is also why neither version should be used as a security token. The random part of a UUID is not guaranteed to come from a cryptographically secure source, and a UUIDv7 telegraphs its own timing. For session tokens, password-reset links, and similar secrets, use a value from a dedicated cryptographic random generator instead.
Which one should you use?
- Internal database primary keys: prefer UUIDv7 for the insert performance, unless you specifically need to hide creation order.
- Public ids exposed in URLs or APIs: UUIDv4, so you do not leak timing or ordering, or a separate opaque id.
- Secrets and tokens: neither; use a cryptographically secure random generator built for the job.
Generate UUIDs locally
The UUID Generator creates UUIDs in your browser, so nothing is sent to a server. The full specification of every version, including the v7 layout and the timestamp field, is RFC 9562, which replaced the older RFC 4122 in 2024.
Generate a UUID nowGenerate 5 random RFC 4122 version 4 UUIDs at once. The input is ignored; run again for a new batch.Related articles
Hashing vs Encryption: What a Hash Can and Cannot Do
Hashing is one-way and keyless; encryption is two-way and needs a key. Learn the difference, why you cannot decrypt a hash, and when to use each.
How Webhook Signatures Work: HMAC, Shared Secrets, and Timing-Safe Checks
How Stripe and GitHub prove a webhook is genuine using HMAC and a shared secret, and the timing-safe comparison most developers get wrong.
Base64 Explained: Why Encoding Is Not Encryption
What Base64 actually does, why it makes data about a third larger, when to use it, and why it protects nothing on its own.