For fifteen years the answer to "which UUID should I use" was simply version 4. It is random, it is everywhere, and every language can make one. Then RFC 9562 arrived in 2024 with version 7, and for a lot of workloads v7 is now the better default. This post explains the difference and gives you a rule to decide.
How UUID v4 is built
A v4 UUID is 122 random bits plus 6 fixed bits for the version and variant markers. That is all. There is no timestamp, no machine ID, no sequence. Two v4 UUIDs generated one nanosecond apart look nothing alike:
f47ac10b-58cc-4372-a567-0e02b2c3d479
3d8e1f0a-9c2b-4e5f-8a1d-7b6c5d4e3f2a
This is a strength when you want IDs that reveal nothing. It is a weakness when you want to sort by creation time or keep a database index compact.
How UUID v7 is built
A v7 UUID starts with a 48 bit Unix timestamp in milliseconds. The remaining 74 bits are random. So the first 12 hex digits encode the time and the rest is noise:
0192a7b3-4c1e-7d2f-9a3b-8c7d6e5f4a3b
0192a7b3-4c1f-7e8a-b1c2-d3e4f5a6b7c8
Two v7 UUIDs generated in the same millisecond share their first 12 characters. One generated a second later has a slightly larger prefix. This means v7 UUIDs sort in creation order when compared as plain strings or bytes.
Why ordering matters for databases
Most databases store primary keys in a B-tree. New keys are inserted at the position where they sort. With v4, every insert lands at a random page in the index. On a table with millions of rows that means the database is constantly touching pages that are not in memory, splitting them, and writing them back. Insert throughput drops and the index grows with fragmentation.
With v7, every new key is larger than the last one, so inserts go to the rightmost page just like an auto increment integer. The hot part of the index stays in cache. On PostgreSQL and MySQL the difference on a busy table can be several times faster inserts and a noticeably smaller index. We cover this in depth in Should You Use UUIDs as Primary Keys?.
What v7 gives away
The timestamp in a v7 UUID is readable by anyone who sees it. If you expose a v7 ID in a public URL, a visitor can work out when that record was created to the millisecond. For most applications that is harmless. For some, such as anonymous submissions, it could be a privacy concern. v4 leaks nothing at all.
v7 also does not tell you how many records exist or what the previous ID was, so it is still much safer than a sequential integer in a URL.
Side by side
| UUID v4 | UUID v7 | |
|---|---|---|
| Random bits | 122 | 74 |
| Sortable by time | No | Yes |
| Index locality | Poor | Good |
| Reveals creation time | No | Yes, to the millisecond |
| Standard | RFC 4122, 2005 | RFC 9562, 2024 |
| Library support | Universal | Most modern libraries |
A simple rule
- If the UUID will be a database primary key or you will ever sort or range scan by it, use v7.
- If the UUID is a secret, such as a password reset token or an unguessable share link, use v4. More random bits is what you want.
- If you need to hide when something was created, use v4.
- If none of the above applies, either works, and v7 is the safer long term choice.
Generating each one
In JavaScript, crypto.randomUUID() gives you a v4 in every modern browser and in Node. For v7 the uuid npm package exports a v7() function. PostgreSQL 18 added a native uuidv7() function, and Python 3.14 added uuid.uuid7() to the standard library. Our guide to generating UUIDs in every language has snippets for each.
You can also make both kinds right now with our online UUID generator. Generate ten v7 UUIDs and watch the prefix tick upward.