glunty

Blog   /   guides   /  

UUID v4 vs v7: which to use

UUID v4 is random, v7 is time-ordered. Learn when to use each version, why v7 works better as a database primary key, and what UUIDs are not.

A UUID looks like a random string until you need to choose which kind to generate, and then the choice matters. The two versions most people reach for today are v4 and v7, and they behave very differently once your data grows. This guide explains what a UUID is, how v4 and v7 differ, and which one belongs in your database.

What a UUID is

A UUID (universally unique identifier) is a 128-bit value. That is 16 bytes, or 32 hexadecimal characters, conventionally written in the 8-4-4-4-12 grouping separated by hyphens: f47ac10b-58cc-4372-a567-0e02b2c3d479. The groups are purely cosmetic; the identity is the 128 bits underneath.

Two of those bits encode the variant, and four encode the version. That is why real UUIDs always have a recognizable digit in fixed positions: the version nibble sits at the start of the third group (the 4 or 7). The remaining bits are what each version fills in differently. The current specification is RFC 9562, which replaced RFC 4122 in 2024 and formally introduced v7.

v4: random

A version 4 UUID is almost entirely random. Of the 128 bits, 6 are fixed for version and variant, and the other 122 are pulled from a cryptographically strong random source. That is the whole design. There is no timestamp, no machine identifier, no ordering. Two v4 UUIDs generated a microsecond apart have no relationship to each other.

This makes v4 excellent when you want opacity and no coordination. Generating one requires no shared state, no clock, and no central authority: any process anywhere can mint one and trust it will not clash. That is why v4 became the default for correlation IDs and generic object identifiers.

v7: time-ordered

A version 7 UUID keeps the same 128-bit shape but reorganizes the layout. The first 48 bits hold a Unix timestamp in milliseconds. The remaining bits (minus the version and variant) are random. The result is a UUID that sorts, roughly, in the order it was created. Sort a pile of v7 UUIDs as text and you get them back in chronological order, because the high bits are the clock.

You still get uniqueness from the random tail, and you still avoid coordination between generators. What you gain is that the value now carries its own creation time in its most significant bits.

Why v7 is better as a database primary key

This is the practical reason v7 exists. Most databases store rows in an index ordered by primary key (a clustered index in SQL Server and InnoDB). When keys arrive in random order, as they do with v4, every insert lands in an unpredictable spot in the index. Pages fragment, the cache thrashes, and the tree is rebalanced constantly. On a large table this is measurable write amplification.

v7 keys arrive in ascending order, so almost every insert appends near the end of the index. This is called index locality: new writes touch the same few pages instead of scattering across the whole tree. Inserts stay fast as the table grows, page splits drop, and range queries by time become trivial because the key order already matches insertion order. If you are choosing a primary key format for a new table today, v7 is usually the better default.

Unique is not the same as secret

A crucial caveat: UUIDs are designed to be unique, not unguessable. Do not treat one as a security token.

v7 is the sharper warning here, because its timestamp prefix leaks when the record was created and makes nearby IDs partly predictable. But even v4, while hard to guess, is not a substitute for a real secret. If you need an unguessable value, generate one deliberately and, where appropriate, store a hash of it rather than the raw value. You can produce a proper digest with the hash generator. Use UUIDs to identify things, and use dedicated secrets to protect them.

Collision probability in practice

People worry about two UUIDs colliding. In practice you can stop worrying. With 122 random bits in v4, you would need to generate a billion UUIDs per second for roughly 85 years before the odds of a single collision reached even one percent. No normal application approaches that. v7 has fewer random bits per value, but those bits only need to be unique within the same millisecond, which still makes a collision negligible. Uniqueness is not the thing that will break.

A note on v1, v3, and v5

The older versions still appear in existing systems. v1 is time-based like v7 but embeds the machine MAC address, which leaked hardware identity and ordered the bits awkwardly for sorting; v7 is the modern replacement. v3 and v5 are deterministic: they hash a namespace plus a name (v3 with MD5, v5 with SHA-1) so the same input always yields the same UUID. Those help when you need a stable ID derived from existing data, but for fresh identifiers reach for v4 or v7.

Which to use

Use v7 for database primary keys and anything you insert in volume, so you get index locality and free time ordering. Use v4 when you want an opaque identifier with no embedded metadata and no ordering signal. When you need to see either version, the UUID generator produces both in your browser with zero requests. Neither one is a secret, so keep your real tokens separate.

Embedded tool from glunty.com