A UUID (Universally Unique Identifier) is a 128-bit value you can generate anywhere without a central coordinator and still be confident it is unique. For years, version 4 (random) was the default. In 2024, RFC 9562 standardised version 7 (time-ordered), and it is quickly becoming the better choice for database keys. This guide explains the trade-off in plain terms. You can generate test UUIDs in our UUID generator.
What is a UUID v4?
A v4 UUID is almost entirely random: 122 of its 128 bits come from a cryptographically secure random source, with the remaining 6 bits fixed to mark the version (4) and variant. A typical v4:
9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
^ version (4)
Its strengths are exactly what you would expect from randomness: it is unguessable and decentralised. No two services need to coordinate to avoid collisions. Our UUID generator produces v4 values using crypto.randomUUID().
What is a UUID v7, and why was it created?
A v7 UUID is time-ordered. Its most significant 48 bits are a Unix timestamp in milliseconds, followed by version/variant bits and then random bits to guarantee uniqueness within the same millisecond:
018f8c1e-7c2a-7b3e-9a4f-2b0d7b3dcb6d
└── unix ms timestamp ──┘^ version (7)
Because the timestamp leads, v7 values created later sort after earlier ones when compared as bytes or strings. That single property fixes the biggest operational problem with v4. If you want to see how that leading timestamp maps to a real date, paste the millisecond value into the Unix timestamp converter.
Why does v4 hurt database performance?
Most databases store a primary key in a B-tree index. When keys arrive in roughly sorted order, new entries append to the end of the tree — cheap and cache-friendly. When keys are random (v4), each insert lands at an unpredictable position, forcing the engine to:
- Read and modify pages all over the index (poor cache locality).
- Split pages frequently, causing fragmentation.
- Write more to disk for the same number of inserts.
On a high-volume table, random primary keys measurably reduce insert throughput and bloat the index. Time-ordered v7 keys avoid this by behaving almost like an auto-incrementing key while staying globally unique.
UUID v4 vs v7 side by side
| Property | UUID v4 | UUID v7 |
|---|---|---|
| Source | 122 random bits | 48-bit ms timestamp + random |
| Order | None (scattered) | Time-ordered, sortable |
| Index locality | Poor | Excellent |
| Reveals creation time? | No | Yes (approximate) |
| Unguessable? | Fully | Mostly (timestamp is visible) |
| Standard | RFC 4122 / 9562 | RFC 9562 (2024) |
| Best for | Tokens, public IDs | Primary keys, event logs |
When should you use each?
Choose v7 when:
- It is a database primary key on a table that sees many inserts.
- You want IDs that naturally sort by creation time (event streams, logs, message ids).
- You would otherwise reach for an auto-increment integer but need global uniqueness.
Choose v4 when:
- The ID is public and the creation timestamp must not leak (password-reset tokens, share links, anything where timing analysis is a concern).
- You need maximum unpredictability and order carries no benefit.
- You are integrating with a system that already expects random UUIDs.
What about security?
Neither version should be treated as a secret on its own. A v4 reveals nothing, but it is still an identifier, not an authorization mechanism — never grant access based solely on knowing a UUID. And remember v7 deliberately exposes a timestamp, so do not use it where that timing is sensitive. If you need a value that is genuinely irreversible (a fingerprint rather than an identifier), that is a job for hashing, not UUIDs — see hashing vs encryption vs encoding.
Practical tips
- Storage: store UUIDs as a native 16-byte type (e.g. PostgreSQL
uuid) rather than a 36-character string to save space and speed comparisons. - Migration: you can switch new rows to v7 without rewriting old v4 rows; both are valid 128-bit UUIDs.
- Generation: generate v4 test data in the UUID generator; for v7 in production, use a library that implements RFC 9562 (most major languages now have one).
Sources
- IETF RFC 9562, Universally Unique IDentifiers (UUIDs) (defines v7, obsoletes RFC 4122).
- IETF RFC 4122, A Universally Unique IDentifier (UUID) URN Namespace.
- PostgreSQL documentation, UUID Type and B-tree index behaviour.