UUID v4 vs v7: Which One Should You Use for Your Next Project?

Mirsal Saidu Updated 8 min read

UUID v4 vs v7 compared with RFC 9562: random vs timestamp-ordered IDs, how each affects database indexes, and which one to pick for your next project.

UUID v4 vs v7: Which One Should You Use for Your Next Project?

Should I use UUID v4 or v7?

When you weigh UUID v4 vs v7, start with what the ID is for. Use UUID v7 for database primary keys or any application where sortability is important. Unlike v4 (which is purely random), v7 includes a timestamp, making it lexicographically sortable. Use UUID v4 when you need pure randomness and don't care about the order of creation. Our UUID generator creates v4 values with the browser's crypto.getRandomValues(). It does not make v7; the section on generating them below lists where to get v7 values.

UUID v4 vs v7: what RFC 9562 says

If the UUID is going to be a database key, I use v7. If it only has to be unique and nothing will ever sort by it, v4 is fine. Both are 128 bits and both are defined in RFC 9562, which replaced RFC 4122 in May 2024. A v4 UUID is 122 random bits plus the 4 version bits and 2 variant bits. A v7 UUID puts a 48-bit Unix timestamp in milliseconds in the most significant bits and fills the remaining 74 bits with random data, again apart from the version and variant bits. Because the time comes first, v7 values sort by creation time both as raw bytes and as text. The RFC says versions that are not time ordered, such as v4, "have poor database-index locality", meaning each new value is inserted at a random spot in the index. The cost of v7 is that anyone holding the ID can read when it was created, down to the millisecond.

PropertyUUID v4UUID v7
Defined inRFC 9562, section 5.4RFC 9562, section 5.7
Total size128 bits128 bits
Version field (4 bits)0100 (4)0111 (7)
Variant field (2 bits)1010
TimestampNone48-bit Unix time in milliseconds, bits 0 to 47
Random bits12274 (12 in rand_a, 62 in rand_b); a generator may use some of them for a counter or sub-millisecond time
Sorts by creation timeNoYes, as bytes or as text; order inside one millisecond depends on the generator (section 6.2)
Where new keys land in an indexRandom positionsNear each other
Reveals when it was createdNoYes, to the millisecond

How to read the UUID v4 vs v7 format

Both versions print as 32 hexadecimal digits in groups of 8, 4, 4, 4 and 12, joined by four hyphens, for 36 characters in total. Each hex digit holds 4 bits, so you can find every field by counting digits. Here is a random v4 value next to the v7 example from the FAQ below:

Hex digitsUUID v4: 197fa107-80a8-478c-b9a0-a19f90c95c87UUID v7: 019b76da-a800-76f3-939f-9155620c2d1e
1 to 12197fa10780a8, random019b76daa800, Unix time in milliseconds (1767225600000)
13 (version)47
14 to 1678c, random6f3, the 12 bits of rand_a
17 (variant)b (binary 1011)9 (binary 1001)
18 to 32randomrest of rand_b

The 13th digit, the first one after the second hyphen, tells you the version at a glance. The 17th digit is always 8, 9, a or b in both versions, because its first two bits carry the variant 10 and the other two bits belong to the random part. That is where the counts in the table above come from: 128 bits minus 4 version bits and 2 variant bits leaves 122 random bits in a v4, and a v7 spends 48 of those on the timestamp, which leaves 74.

UUID v4 vs v7 length and size

Neither version is longer. Both are 16 bytes as binary and 36 characters as text, or 32 characters if you strip the hyphens (the generator has a Remove hyphens option for that). The storage choice matters more than the version. A native type such as PostgreSQL's uuid or a BINARY(16) column keeps the 16 bytes, while a CHAR(36) column stores 36 characters per key. JSON has no UUID type, so in an API response either version travels as a 36-character string; what is JSON covers the value types JSON does have.

Example: three UUID v7 values in creation order

These three v7 values were built for 2026-11-06 12:00:00.000 UTC, one millisecond later, and one second later. The number after each ID is its 48-bit timestamp in milliseconds:

01a1b0ba-e200-752e-89a7-834df2a74de4   1793966400000   2026-11-06 12:00:00.000 UTC
01a1b0ba-e201-7651-8317-1ff4a6a3a450   1793966400001   2026-11-06 12:00:00.001 UTC
01a1b0ba-e5e8-7128-a24b-e40ad23f0824   1793966401000   2026-11-06 12:00:01.000 UTC

The first two IDs share their first 11 hex digits, and the one-millisecond step shows up as e200 becoming e201. One second is 1,000 milliseconds, or 0x3e8, so the third ID reads e5e8. A plain text sort or a byte sort puts the three in the order they were made, which is what keeps new primary keys next to each other in an index. Sort a list of v4 values and the order has nothing to do with when they were created.

To read the time back by hand, convert the first 12 hex digits to decimal (int("01a1b0bae200", 16) in Python gives 1793966400000) and paste the number into the Unix timestamp converter with the unit set to milliseconds. Hex and decimal are two spellings of the same number, which Base64 vs hex encoding explains in more detail.

Why UUID v4 slows down database indexes

When you use v4 as a database key, your database has to insert records into random locations in its index. That causes page fragmentation and slows down writes as the table grows. When I switched a high-volume logging service from v4 to v7, we saw a measurable decrease in disk I/O because the new records were always being appended to the end of the index.

The effect is strongest when the UUID is the database primary key. MySQL's InnoDB stores the table rows themselves in primary key order, so random v4 keys scatter inserts across the table itself. In PostgreSQL the primary key is a separate B-tree index, and random keys still mean each insert can touch a different page of it. With v7, consecutive inserts land on the same few pages at the right-hand edge of the tree, the part most likely to be in memory already.

Collision resistance

v7 has fewer random bits than v4, 74 against 122, but those 74 bits only have to tell apart IDs created in the same millisecond, so collisions are still very unlikely. RFC 9562 (section 6.7) leaves it to each application to weigh how much a collision would cost.

In numbers: with 122 random bits you would need about 2.7 × 10¹⁸ v4 values before the chance of a single duplicate reaches 50%. The same birthday calculation for v7 applies only to IDs that share a millisecond, and comes to about 1.6 × 10¹¹ IDs inside one millisecond. Creating a million v7 IDs in the same millisecond gives a duplicate chance of roughly 2.6 × 10⁻¹¹.

How to generate UUID v4 and v7 values

The UUID generator on this site makes version 4 only. It creates 1 to 100 values at a time with crypto.getRandomValues(), can switch them to uppercase or remove the hyphens, and has Copy All and Copy First buttons. For v7 you need a generator that reads the clock:

  • PostgreSQL 18 has uuidv7(), plus uuidv4() and the older gen_random_uuid() for v4. Its UUID functions page says uuidv7() combines a millisecond Unix timestamp, a sub-millisecond timestamp and random bits, and accepts an optional interval to shift the time. PostgreSQL 17 and older have no built-in v7 function, so generate the value in your application.
  • Python 3.14 added uuid.uuid7(). The uuid module docs say it uses a 42-bit counter to keep IDs in order within one millisecond, which is one of the options RFC 9562 allows for those 74 bits. From a shell, python3 -m uuid -u uuid7 prints one.
  • Node's crypto.randomUUID() and the browser's crypto.randomUUID() return v4.

In PostgreSQL 18, a table that uses v7 keys and reads the time back looks like this:

CREATE TABLE orders (
  id uuid PRIMARY KEY DEFAULT uuidv7(),
  total_cents integer NOT NULL
);

SELECT id, uuid_extract_version(id), uuid_extract_timestamp(id) FROM orders;

When UUID v4 is still the better choice

  • The ID appears in URLs or exports and the creation time is private: a v7 customer ID reveals when the account was opened.
  • Nothing sorts or indexes by the ID: a request ID in a log line, a file name, or the jti claim that gives a token a unique ID (see how to decode a JWT safely for what else a token carries).
  • An existing table already uses v4 and performs well. Switching only changes new rows, and sorting by ID will not be chronological for the old ones.

Neither version is a secret. RFC 9562, section 8, says implementations should not assume UUIDs are hard to guess and must not use them as security capabilities, meaning identifiers whose possession alone grants access. A v7 is easier to narrow down than a v4 because 48 of its bits are a timestamp. For password reset links, invite codes or API keys, use a long random string from the password generator or your framework's token function.

UUID v4 vs v7 vs ULID

ULID is a separate specification with the same idea as v7: a 48-bit millisecond timestamp followed by 80 random bits, written as 26 characters of Crockford Base32. It has no version or variant bits, so it is not an RFC 9562 UUID, and a function such as uuid_extract_version() returns a meaningless result or null for it.

If your database has a native uuid type and you are starting a new schema, v7 gives you the time ordering of a ULID in a format every UUID column, library and driver already accepts.

Frequently asked questions

Is UUID v7 a standard?

Yes, it was standardized in RFC 9562 in May 2024. RFC 9562 recommends v7 over the older time-based versions 1 and 6, and its time ordering makes it a good fit for database keys.

Can anyone read the creation time from a UUID v7?

Yes. The first 12 hex digits are the Unix timestamp in milliseconds. In 019b76da-a800-76f3-939f-9155620c2d1e, 019b76daa800 is 1767225600000, which is 2026-01-01 00:00:00 UTC. If IDs are visible to users and creation time is sensitive, use v4.

Can I mix UUID v4 and v7 in the same column?

Yes. Both are valid 128-bit UUIDs, so a uuid column accepts either, and the version digit tells them apart later. New v7 rows will sort by time among themselves, while older v4 rows keep their random order, so do not rely on ORDER BY id for history that spans the switch.


Share this article:
Mirsal Saidu

Mirsal Saidu

Digital & Performance Marketer