LocalFirstTools.com — data tools that never leave your device
No upload — everything runs on your device

UUID v4 vs v7: random or time-ordered?

Last updated

UUID v4 is 122 bits of pure randomness; UUID v7 (standardized in RFC 9562, May 2024) starts with a 48-bit Unix millisecond timestamp, so v7 IDs sort by creation time. Choose v4 when IDs must reveal nothing; choose v7 when the IDs become database keys and insert performance matters. The UUID Generator produces v4 — the browser's own crypto.randomUUID() — honestly labeled as such; it does not generate v7.

Anatomy of each

v4:  ff2154a1-b2c3-4d81-9f3e-8a72e05c1d44
     └────────── random ──────────┘  (122 random bits; "4" = version)

v7:  0198f0a4-7e12-7cc3-9a41-d0b3a1c65f02
     └─ 48-bit ms timestamp ─┘└─ random ─┘  ("7" = version)

Both are 128 bits in the same 36-character format, both carry version and variant markers, and both rely on randomness against collisions — v7 simply spends its first 48 bits on time (milliseconds since the Unix epoch — the same unit explained in seconds vs milliseconds) and keeps 74 random bits.

The exact bit layout

RFC 9562 section 5.7 lays v7 out like this (v4 is the same frame with random bits everywhere):

v7:  unix_ts_ms   48 bits   milliseconds since 1970-01-01 UTC
     ver           4 bits   0111 (7)
     rand_a       12 bits   randomness (or sub-ms precision)
     var           2 bits   10 (RFC variant)
     rand_b       62 bits   randomness

v4:  122 random bits around the same ver=0100 and var=10 markers

Two consequences worth knowing. First, a v7 UUID's creation time is recoverable: the first 12 hex characters are the millisecond timestamp, so 0198f0a4-7e12-… decodes to a concrete instant (48 bits of milliseconds run out in the year 10889 — nobody's problem). Second, the version and variant nibbles are why you can eyeball any UUID: third group starts with 4 → v4, with 7 → v7.

How unlikely is a collision, concretely?

With 122 random bits (v4), the birthday bound says you need roughly 261 ≈ 2.3×1018 UUIDs for a 50% chance of a single collision. Generating one billion UUIDs per second, that is about 73 years of continuous output — and the “collision” would be one duplicate somewhere in that entire mountain. v7's 74 random bits per millisecond give about 1.9×1022 possible values within each millisecond, so the practical answer is the same for both: treat collisions as impossible, and treat any observed duplicate as a bug in the generator (a forked process reusing entropy, a copy-paste) rather than bad luck.

Why time-ordering matters for databases

B-tree indexes love sequential inserts. v4 keys land at random positions across the index, so every insert touches a random page — cache misses, page splits, write amplification, and the problem grows with table size. v7 keys are monotonically increasing (per millisecond), so inserts append to the same hot pages, like an auto-increment integer but globally unique. As a bonus, ORDER BY id approximates creation order without a separate timestamp column, and recent rows cluster physically together.

When v4 is still the right answer

  • Unlinkability. v4 IDs reveal nothing — no creation time, no ordering. Public tokens, password-reset codes and IDs in URLs often should not leak when they were made.
  • Zero dependencies. crypto.randomUUID() is built into every modern browser and Node ≥ 19, cryptographically seeded, no library needed — generate one now.
  • Not a database key. Request IDs, idempotency keys, trace IDs and file names gain nothing from ordering.

The rest of the version family, briefly

v1 is the original time-based UUID — timestamp plus the machine's MAC address, which leaked hardware identity and made it privacy-notorious; v7 is effectively its rehabilitated successor. v5 is deterministic: it hashes a namespace plus a name (with SHA-1, used here as a name-mapper, not for security) so the same input always yields the same UUID — useful for stable IDs derived from URLs or external keys. v8 is a free-form escape hatch for custom layouts. v2, v3 and v6 exist but are legacy or niche. For new work the realistic menu is: random (v4), time-ordered (v7), or deterministic (v5).

Rule of thumb

Primary key in a relational database → v7, generated server-side with a library. Everything else → v4. And never derive either from hashing user data — a hash of an email is deterministic and linkable, the opposite of what a UUID is for.

Do it now — locally

Create version 4 UUIDs with the Web Crypto API. Nothing is uploaded.

Open the UUID Generator

Frequently asked questions

Can v7 UUIDs collide?

Practically no. Two v7 UUIDs generated in the same millisecond still differ in 74 bits of random data. Collisions require both the same millisecond and the same random bits — astronomically unlikely.

Do v7 UUIDs leak information?

The timestamp, yes — anyone holding a v7 UUID can read when it was created, to the millisecond. If creation time is sensitive (say, IDs exposed in URLs reveal signup dates), that is a real consideration in favor of v4.

Is UUID v7 widely supported?

Support arrived quickly after RFC 9562 (May 2024): PostgreSQL 18 has uuidv7(), and libraries exist for every major language (the uuid npm package, Python's uuid6 package, and others). The browser's built-in crypto.randomUUID() still generates only v4.

Should I migrate existing v4 keys to v7?

Usually not — the win applies to newly inserted rows' index behavior, and changing primary keys is invasive. New tables and new systems are where v7 is worth choosing.

How do I read the timestamp out of a v7 UUID?

Take the first 12 hex characters (skip the dashes), parse as a hex integer, and you have Unix milliseconds: parseInt(uuid.replaceAll('-','').slice(0,12), 16). Convert that with the timestamp tool to see the creation instant.

Are sequential IDs (auto-increment) still better than v7?

For a single database they are smaller (8 bytes vs 16) and equally index-friendly. v7 wins when IDs must be generated on many machines without coordination, must not reveal row counts, or need to be globally unique across systems. That trade — coordination-free uniqueness for 8 extra bytes — is the whole UUID proposition.