UUID v4 vs v7: Differences, Format and Which One to Use
UUID v4 vs v7 explained: how each is built, how to read the timestamp in a v7, collision odds and which to pick for database keys and public IDs.
By TheTextKit TeamPublished

Two example UUIDs. The v4 is fully random. The v7 starts with a timestamp, shown in blue, followed by random digits.
UUID v4 is 122 random bits wrapped in a fixed layout. UUID v7 replaces the first 48 bits with the current Unix time in milliseconds and fills the rest with random bits, so its values sort by creation time. Use v7 for database primary keys that take many inserts, and v4 when an ID is public and its creation time should stay private, or when your language has no v7 yet. This guide covers how each is built, how to read the time inside a v7, the collision math, and a simple rule for choosing.
UUID v4 vs v7: the short answer
Both are 128-bit identifiers written as 36 characters. The standard that defines them is RFC 9562, published in May 2024, which obsoleted RFC 4122 and added versions 6, 7 and 8.
| UUID v4 | UUID v7 | |
|---|---|---|
| Made from | Random bits only | 48-bit Unix time in ms, then random bits |
| Random bits | 122 | 74 |
| Sorts by creation time | No | Yes, to the millisecond |
| Reveals when it was made | No | Yes, to the millisecond |
| Best for | Public IDs, quick tokens for tests | Database primary keys, event logs |
| In the browser | crypto.randomUUID() | No built-in function |
| In PostgreSQL | uuidv4() or gen_random_uuid() | uuidv7() (version 18 and later) |
One detail worth knowing: RFC 9562 says implementations should use v7 instead of the older v1 and v6 where possible. It does not say v7 should replace v4. The choice between them is yours.
How a UUID is built
Every UUID is 16 bytes, or 32 hex digits, grouped 8-4-4-4-12 with hyphens. Two spots tell you what you are holding: the first character of the third group is the version, and the first character of the fourth group (8, 9, a or b) marks the RFC variant.
Here is a v4 and a v7. The v4 came from crypto.randomUUID(), and the v7 was built to the RFC layout for 14 October 2026, 09:30:00.123 UTC:
58334adf-46e1-4adf-9c07-f8a38c65743f (version digit 4)
01a139bf-4a3b-734f-b6f8-e7cc807673bd (version digit 7)
The bit layout in UUID v4 vs v7, from RFC 9562 sections 5.4 and 5.7, is the same shape with different contents:

Two bars of 128 bits. Both split into 48, 4, 12, 2 and 62 bits. In v4 everything but the version and variant bits is random. In v7 the first 48 bits are a timestamp.
In v4, only 6 of the 128 bits are fixed (4 for the version, 2 for the variant), which leaves 122 random bits. In v7, the first 48 bits are the timestamp, the same 6 are fixed, and the remaining 74 are random.
How to read the time inside a UUID v7
Because the first 48 bits are Unix milliseconds, you can decode a v7 by hand:
- Remove the hyphens and take the first 12 hex digits:
01a139bf4a3b. - Convert them to decimal: 1791970200123.
- Read that as milliseconds since 1 January 1970 UTC: 2026-10-14 09:30:00.123 UTC.

Step one highlights the first 12 hex digits of a v7. Step two shows them as the decimal 1791970200123. Step three reads that as 14 October 2026, 09:30:00.123 UTC.
Paste the decimal number into the Unix Timestamp & Epoch Converter. It treats a number of 12 or more digits as milliseconds and shows the UTC date. Our guide on how to convert a Unix timestamp to a date explains the seconds versus milliseconds trap in detail.
A 48-bit millisecond counter does not run out soon. PostgreSQL's documentation puts the limit at about the year 10889.
Why v7 is easier on database indexes
A primary key index keeps its values in order. With v4, every new key lands at a random position, so inserts touch pages all over the index. With v7, the newest key is almost always the biggest one, so inserts pile up at the end, much like an auto-increment number. That is the problem RFC 9562 section 2.1 describes when it says many large applications went looking for a better time-based, sortable identifier for database keys. PostgreSQL 18, released on 25 September 2025, added uuidv7(), which its announcement says supports better caching strategies.
We ran a small seeded simulation to make the effect visible: 20,000 keys inserted one after another, counting how many landed in the newest 1% of the index.

Two strips from oldest to newest key. The last 150 v4 inserts are scattered across the strip, 1.1 percent in the newest 1 percent. All the v7 inserts sit at the newest end, 100 percent.
Only 1.1% of the v4 keys landed there, which is what chance predicts. Every v7 key did. This shows where keys go, not how fast a database runs, so treat it as an illustration and measure your own workload before you migrate.
How likely is a UUID collision?
For random bits, the birthday approximation says the chance of any duplicate among n values is about n² divided by twice the number of possibilities. For v4 that is 2 to the power 122, about 5.3 followed by 36 zeros.
| UUIDs generated | Chance of any duplicate (v4) |
|---|---|
| 1 million | about 9.4 in 1026 |
| 1 billion | about 9.4 in 1020 |
| 1 trillion | about 9.4 in 1014 |
| 2.7 quintillion | about 50% |
At a million UUIDs a second, reaching 2.7 quintillion takes roughly 86,000 years. For v7 the random part is only 74 bits, but it matters only among IDs created in the same millisecond. Generate 1,000 in one millisecond and the odds of a repeat are about 2.6 in 1017. Both are fine in practice, provided the random bits come from a cryptographically secure generator, as RFC 9562 section 6.9 recommends.
What a v7 gives away
The timestamp is the one real trade-off in UUID v4 vs v7. Anyone holding a v7 can read when the record was created, and a run of v7 values reveals how fast you create them. If an ID appears in a public URL and your growth rate or the age of an account is sensitive, use v4.
Neither version is a secret. RFC 9562 section 8 states that implementations should not assume UUIDs are hard to guess and that they must not be used as security capabilities. For a password or reset token, use the Password Generator or your framework's token function. For a fingerprint of a file or record, a hash is the right tool: see the Hash Generator and our guide to MD5 vs SHA-256.
UUID v4 vs v7: which one should you use?

Two columns. v7 for database primary keys, tables with heavy inserts and sorting by creation time. v4 when creation time must stay private, when your stack has no v7 yet and for quick IDs in the browser.
Use v7 for primary keys on tables that take many inserts, for event and log IDs you will sort by time, and anywhere you want the ID itself to carry an approximate creation time.
Use v4 for public identifiers where creation time must stay private, for IDs generated in a browser, and when your database or language has no v7 function yet. Python added uuid.uuid7() in 3.14, and PostgreSQL added uuidv7() in 18.
Mixing is fine. A uuid column holds both, and the version digit tells you which is which. Existing v4 rows will not move, and new v7 rows will cluster at the end.
Do not expect order inside one millisecond. A plain v7 fills the rest with random bits. In our test of 1,000 values made in the same millisecond, only 507 of 999 neighbouring pairs were ascending. Python's uuid7() adds a 42-bit counter to guarantee order within a millisecond, which is the kind of detail to check in your library.
Store them as a native type. PostgreSQL's uuid type stores 128 bits, not 36 characters of text, and accepts uppercase, braces and missing hyphens on input while always printing the standard lowercase form.
Generate UUIDs in your browser
The UUID Generator makes up to 50 version 4 UUIDs at a time using crypto.randomUUID(), which MDN describes as a v4 UUID from a cryptographically secure generator, available only on HTTPS pages. Where that function is missing, the tool falls back to crypto.getRandomValues() and sets the version and variant bits itself. Nothing leaves your browser.
For v7, use the UUID v7 Generator, which makes time-ordered IDs, keeps a batch in order with the RFC's counter method and decodes the time inside any UUID. In a database, use SELECT uuidv7(); in PostgreSQL 18 or uuid.uuid7() in Python 3.14, then paste the result into the decoder or the timestamp converter to check the time inside.
Frequently asked questions
Is UUID v7 better than v4?
For database primary keys, usually yes: v7 values sort by creation time, so new rows land at the end of the index instead of all over it. For public IDs that must not reveal when something was created, v4 is the safer pick. Neither is a secret.
Can I mix v4 and v7 in the same column?
Yes. Both are valid 128-bit UUIDs in the same 8-4-4-4-12 format, so a uuid column accepts either. The version digit, the first character of the third group, tells them apart. Mixing just means old v4 rows sort randomly among the time-ordered v7 rows.
Is UUID v7 sortable?
By millisecond, yes. In a test of 1,000 plain v7 values made in the same millisecond, only 507 of 999 neighbouring pairs were in ascending order, which is chance. Order within one millisecond needs a counter, which some libraries add, such as Python 3.14.
Can you tell when a UUID v7 was created?
Yes, to the millisecond. The first 12 hex digits are a Unix timestamp in milliseconds. Drop the hyphens, convert those digits to decimal and read the result as a date. A v4 contains no time at all.
Should I use a UUID as a password or access token?
No. RFC 9562 says implementations should not assume UUIDs are hard to guess and must not use them as security capabilities. Use a purpose-built random token for secrets, and keep UUIDs for identifying records.
Pick your version before the first insert
Changing an ID format later means touching every foreign key, so settle the UUID v4 vs v7 question early. If the ID is internal and the table will grow, start with v7. If the ID is public, or your stack lacks v7, start with v4 and move on. Generate a few v4 values in the UUID Generator, and decode any v7 you meet with the timestamp converter.


