UUID versions explained — v1 through v8
A side-by-side comparison of every UUID version defined by RFC 9562. What each is, when to reach for it, and what to avoid.
By uniqueid.tech — an independent developer based in New Zealand Updated 1 June 2026
Universally Unique Identifiers (UUIDs) are 128-bit values originally standardised in RFC 4122 (2005) and updated in RFC 9562 (May 2024). The standard now defines eight version variants — v1 through v8 — each with different generation rules, properties, and use cases. This guide walks through every version, explains what each is designed for, and offers recommendations for which to pick today.
How UUIDs encode their version
A UUID's canonical text form is 32 hexadecimal characters arranged in
five hyphenated groups:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx (8-4-4-4-12). The
character at position M encodes the version (1 through 8).
The high bits at position N encode the variant — for
RFC-defined UUIDs this is typically 8, 9,
a, or b. Given any UUID, you can identify its
version at a glance by reading that single character.
The remaining 122 bits carry the actual identifier payload. How those bits are filled is what distinguishes the versions.
Version 1 — timestamp and node
UUID v1 combines a 60-bit timestamp (counted in 100-nanosecond intervals since 15 October 1582, the start of the Gregorian calendar) with a 14-bit clock sequence and a 48-bit node identifier. The node identifier was originally the generating machine's MAC address.
Properties. Unique across systems without coordination, because the MAC address provides spatial uniqueness while the timestamp provides temporal uniqueness.
Drawbacks. Two significant ones. First, embedding the MAC address leaks information about the generating system — a serious privacy concern that contributed to v1 falling out of favour. Second, the timestamp fields are laid out with the least significant bits first, so v1 UUIDs do not sort by creation time when compared as strings or bytes.
Use today. Mostly historical. Some legacy systems still
emit v1. Microsoft SQL Server's NEWSEQUENTIALID() produces
something close to a v1 UUID, with the trailing values chosen to play
nicely with SQL Server's particular sort order on the
uniqueidentifier type.
Version 2 — DCE Security
UUID v2 is defined by the Distributed Computing Environment (DCE) 1.1 specification rather than the IETF RFCs. It resembles v1 but replaces the low 32 bits of the timestamp with a POSIX user ID or group ID, used for embedding identity information in the UUID itself.
Use today. Essentially none outside the legacy DCE/Apollo systems it was designed for. Most language standard libraries do not even implement v2 generation — .NET, Python, and Java offer no built-in support. If you've seen v2 mentioned and wondered what it does, the practical answer is "nothing you need to worry about."
Version 3 — MD5 namespace
UUID v3 is the first of the deterministic variants. It takes a namespace UUID and a name string, concatenates them, hashes the result with MD5, and formats the hash into a UUID (overwriting six bits with the version and variant markers).
Key property. Determinism. The same namespace and name always produce the same UUID, with no coordination between systems required.
Drawbacks. MD5 is cryptographically broken — collision attacks against MD5 are practical. For pure identifier generation this doesn't matter (you're not relying on MD5 for security), but since v5 uses SHA-1 and is otherwise identical in shape, there's no compelling reason to pick v3 for new work.
Use today. Only when interoperating with existing systems that emit v3. Otherwise pick v5.
Version 4 — random
UUID v4 is the workhorse: 122 random bits with the version and variant
bits in fixed positions. It's the format produced by
Guid.NewGuid() in .NET, crypto.randomUUID() in
browsers, uuid.uuid4() in Python, and the default in
countless ORMs and frameworks.
Properties. Simple, well-distributed, no information leakage. With 122 bits of randomness, collisions are astronomically improbable for any practical workload.
Drawbacks. A poor fit as a database primary key for high-write tables. Random insertion order causes B-tree index fragmentation and reduces cache locality, slowing inserts and bloating index storage.
Use today. Excellent for non-database identifiers, for IDs where creation order should not be inferable, and for any scenario where insertion order into a sorted structure doesn't matter. Try the UUID v4 generator.
Version 5 — SHA-1 namespace
UUID v5 is structurally identical to v3 but uses SHA-1 instead of MD5. The same namespace and name produce the same UUID; SHA-1's collision resistance is better than MD5's.
Properties. Deterministic ID generation from existing data — generate a stable UUID from a URL, an external system's key, a tuple of values, anything where you want repeat runs to produce the same identifier.
Standard namespaces. RFC 9562 defines four — DNS, URL, OID, and X.500. For application-specific data, generate one v4 UUID once to serve as your custom namespace and reuse it consistently across your system.
Use today. The right choice for deterministic ID generation. Prefer over v3 in all cases. Try the UUID v5 generator.
Version 6 — reordered v1
UUID v6 was added in RFC 9562. It carries the same fields as v1 — timestamp, clock sequence, node — but rearranges the timestamp bits so the most significant bits come first. This makes v6 UUIDs sortable by creation time when compared as canonical strings or as binary (in RFC byte order).
The node field can be a real MAC address or a random 48-bit value with bit 0 of the first octet set to 1 to indicate it's not a real MAC. In practice — and especially in browsers, which cannot access MAC addresses — random nodes are universal.
Use today. Primarily a migration path. If you have an existing v1 system and want better index locality without changing the conceptual format, v6 fits cleanly. For greenfield work, v7 is usually a better fit: simpler, more random bits, no clock sequence to manage. Try the UUID v6 generator.
Version 7 — Unix timestamp and random
UUID v7 is RFC 9562's headline addition. It packs a 48-bit Unix millisecond timestamp into the high bits and fills the remaining 74 bits (after version and variant) with cryptographic randomness.
Properties. Sortable by creation time when compared as
canonical strings or as RFC-correct binary. No MAC address. No clock
sequence to manage. Simple to generate. Native support landed in
.NET 9 (Guid.CreateVersion7()), and most other major
runtimes either already support it or are adding it.
Caveats. The timestamp is exposed — anyone holding a
v7 UUID can decode the creation millisecond. If creation time is
sensitive, use v4 instead. Also, in .NET specifically, watch the
byte-order issue with Guid.ToByteArray() — see
the dedicated
article for the details.
Use today. The recommended default for new database primary keys and for any time-ordered identifier needs. Try the UUID v7 generator, or see UUID v7 in PostgreSQL for a database-specific walkthrough.
Version 8 — custom
UUID v8 is the explicit escape hatch in RFC 9562. It provides 122 bits of application-defined data with no rules about how to fill them — the implementation must only set the version and variant bits correctly. v8 exists so vendors and applications can define UUID-shaped identifiers without colliding with future standardised versions.
Use today. Niche. Most users will never need v8 directly. If you're encoding application-specific data into UUID-shaped IDs (sharding keys, multi-tenant prefixes, embedded sequence numbers), v8 is the version field to claim so future RFC updates won't collide with your format.
Which version should you use?
A short decision guide for new projects:
- General-purpose IDs, no ordering needed: v4
- Database primary keys: v7
- Deterministic IDs from existing data: v5
- Custom application-specific format: v8
- Migrating from v1 and want better index locality: v6
- Anything else: probably v7 or v4
For everything else — v1, v2, v3 — the answer is almost always "use a more recent version unless you're constrained by interop with an existing system."
See also. Choosing a UUID version is a narrower question than choosing an identifier strategy in the first place. For the broader problem of producing unique IDs across many independent processes, see generating IDs in distributed systems. If you're weighing UUIDs against auto-incrementing integer keys, see UUID vs auto-increment primary keys; if you're weighing them against a shorter, URL-friendly format, see NanoID vs UUID.
Common pitfalls
A few errors that recur regardless of version:
Storing UUIDs as strings. A canonical UUID string is 36 characters; the binary representation is 16 bytes. For high-volume tables the storage difference compounds significantly, both in row size and in index size.
Trusting platform byte order. .NET's
Guid.ToByteArray() returns bytes in a non-RFC layout
(little-endian first three fields). SQL Server's
uniqueidentifier type uses yet another layout.
Cross-platform UUID handling needs explicit byte-order management at
every boundary —
see the .NET v7
byte-order article for the most-common form of this bug.
Using non-cryptographic random sources for v4.
JavaScript's Math.random() is not cryptographically secure.
UUIDs derived from it should not be used for security-sensitive
purposes like session tokens — always use
crypto.randomUUID() or equivalent.
Assuming v1 or v6 require a MAC address. Both versions permit random node values, and most modern implementations use them by default.