//: # ()
Need to generate or decode a UUID right now? Use our free UUID Generator & Inspector — create v4 or v7 UUIDs in bulk, or paste one in to see its version, variant, and embedded timestamp.
Auto-incrementing integer IDs are simple, but they leak information (a competitor can estimate your signup rate from sequential user IDs) and they don't work well when multiple systems need to generate IDs independently without coordinating — think distributed systems, offline-first mobile apps, or merging data from multiple databases. A UUID (Universally Unique Identifier) solves this: 128 bits, generated independently, collision probability low enough to ignore in practice.
But "UUID" isn't one format — it's a family, and the version you pick has real, measurable consequences for database performance.
A v4 UUID is 122 bits of randomness (the other 6 bits are fixed to mark version and variant). That randomness is exactly what makes it unpredictable and safe to expose publicly — but it's also the problem for databases.
Most relational databases (PostgreSQL, MySQL/InnoDB, SQL Server) store primary keys in a B-tree index, physically ordered by key value. Insert a random v4 UUID, and the database has to insert it into a random position in that tree — not append it to the end. At small scale this doesn't matter. At scale, it causes:
This is a well-documented, measurable problem — see Percona's benchmarks on UUID primary keys for real numbers on the throughput cost.
UUID v7 (standardized in RFC 9562 in 2024) fixes exactly this, by construction:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms | ver | rand_a |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The first 48 bits are a millisecond-precision Unix timestamp. Everything after that is still random (74 bits — plenty of entropy to avoid collisions), but because the leading bits are time-based, UUIDs generated later always sort after ones generated earlier. That single property means:
created_at lookup (though you should still keep one — the timestamp precision and clock trust model aren't a substitute for an actual timestamp column)| UUID v4 | UUID v7 | |
|---|---|---|
| Sortable by creation time | No | Yes |
| Index-friendly for DB primary keys | No (fragmentation) | Yes (append-like) |
| Fully unpredictable | Yes | Partially (timestamp is visible) |
| Best for | Public-facing tokens, session IDs, anything where hiding when it was created matters | Primary keys, especially at scale |
If you're choosing a primary key type for a new table today and your database and drivers support it, v7 is the better default — you get UUID's distributed-generation benefits without the B-tree performance tax. Reach for v4 specifically when you need creation time to stay hidden, like a password-reset token or an API key.
Generate v4 or v7 UUIDs in bulk, or paste one in to decode its embedded timestamp, with the UUID Generator & Inspector — entirely client-side.