ToolzYard Blog

Developer guides and tutorials

Identifiers Guide

What Is a UUID? UUID v4 Explained with Examples (and Collision Odds)

Published: June 26, 2026 • Updated: July 10, 2026 • By , Founder of ThreeWorks

UUIDs are everywhere in modern software: database primary keys, API resource IDs, file names, session tokens, distributed event IDs, and more. They look like a random jumble of hex digits separated by dashes, but that string is not as random as it appears — a few of its bits are structural, and once you can read them you can tell at a glance how a UUID was generated and whether it is the right one for your job. This guide covers the anatomy of a UUID, the history behind the current standard, the full "version zoo" from v1 to v8, and how to choose between them.

What a UUID actually is

UUID stands for Universally Unique Identifier: a 128-bit value designed to be unique across both space and time without any central coordinator. It was first defined for the web by RFC 4122 in 2005, but that document was formally obsoleted in May 2024 by RFC 9562, which is the current specification. RFC 9562 kept everything that existed and added three new versions (v6, v7, v8) plus a proper Max UUID — so if a library or article still cites only RFC 4122, it predates the modern time-ordered formats.

A UUID is normally written as 32 hexadecimal characters split into five groups by hyphens, in the pattern 8-4-4-4-12:

f47ac10b-58cc-4372-a567-0e02b2c3d479

The hyphens are purely cosmetic. What surprises people is that the 128 bits are not all payload: 4 bits are reserved to encode the version and 2 more encode the variant (the bit layout family). That is why even a "fully random" v4 UUID has only 122 bits of entropy, not 128 — six bits are spent telling parsers how to interpret the rest.

How to read a UUID by eye

Two specific characters carry the structure, and their positions are fixed by the spec:

  • The 13th hex digit (the first character of the third group) is the version number — 1 through 8.
  • The 17th hex digit (the first character of the fourth group) is the variant. For the standard RFC layout it is always 8, 9, a, or b. Anything else means the value follows an older Microsoft or NCS layout, not RFC 9562.
f47ac10b-58cc-4372-a567-0e02b2c3d479
              │        │
           version 4  variant (a)

So the example above is a version 4 UUID with the standard variant. This is a genuinely useful skill: when you are staring at an ID in a log and wondering whether it is time-sortable, you do not need a library — you read digit 13. A 7 there means the front of the string is a timestamp; a 4 means it is noise.

The version zoo

"Version" does not mean newer-is-better; it means a different generation algorithm. Each has a distinct trade-off between randomness, determinism, and sortability.

Version Built from What it gives you
v1 60-bit timestamp + node ID (usually the MAC address) Time-ordered, but leaks the generating host and the moment it was created
v2 DCE Security (POSIX UID/GID embedded) Almost never used; most libraries do not even implement it
v3 MD5 hash of namespace + name Deterministic — same input always yields the same UUID
v4 122 random bits General-purpose unique IDs; no order, no meaning, the common default
v5 SHA-1 hash of namespace + name Deterministic like v3 but preferred over it (SHA-1 > MD5)
v6 Field-reordered v1 Same data as v1 but arranged so the string sorts by time lexicographically
v7 48-bit Unix-millisecond timestamp + random Time-sortable without leaking a MAC address; the modern database-key default
v8 Whatever you want (vendor/custom) An escape hatch for experimental or application-specific layouts

Two things trip people up here. First, v3 and v5 are deterministic: they are hashes, not random draws, so uuid5(DNS_namespace, "example.com") returns the exact same UUID on every machine forever. That makes them ideal as stable IDs derived from natural keys — but useless when you want unpredictability. Second, v1 leaks information: the classic 2000s use of the machine's MAC address as the node field means an old v1 UUID can reveal which server minted it and roughly when. That was famously used to help trace the author of the Melissa virus.

Choosing a version

Most decisions collapse to three questions:

  • Do you need the same input to always produce the same ID? Use v5 (namespaced SHA-1 hash). This is the right tool for deduplicating records by a natural key or generating a stable ID for a URL.
  • Do you need the IDs to sort in creation order (typically for database keys)? Use v7. Its millisecond timestamp prefix means new rows land near each other in an index instead of scattering.
  • Do you just need a unique, opaque, unguessable value? Use v4. It is the safe default for API resource IDs, idempotency keys, and object-storage filenames.

Avoid v1 in new systems (host/time leakage), skip v2 entirely, and prefer v5 over v3. The v4-versus-v7 trade-off for clustered database indexes — and the collision math behind "unique" — is worked out in detail on the UUID Generator tool page; the short version is that 122 random bits make an accidental v4 duplicate something you can safely ignore in any real system.

The GUID-versus-UUID endianness trap

A GUID (Globally Unique Identifier) is Microsoft's name for the very same 128-bit value. For most purposes UUID and GUID are interchangeable, but there is one interoperability trap that has cost real teams real hours. Historically Microsoft stored the first three fields little-endian in memory, while RFC UUIDs are big-endian. When those raw bytes are serialized, the same 16 bytes render as a different string in .NET's System.Guid than in a Java, Python, or PostgreSQL library. If you write a GUID as bytes on Windows and parse those bytes as a UUID elsewhere, the first three hyphen groups come out byte-swapped and your "same" ID silently no longer matches. The fix is to agree on a canonical text form (or a specific byte order) at every boundary rather than shipping raw bytes between ecosystems.

The nil and Max UUIDs

Two special values are worth knowing. The nil UUID is all zeros — 00000000-0000-0000-0000-000000000000 — and RFC 9562 also defines a Max UUID of all Fs. Both are legal, valid UUIDs. The nil is a common footgun: it is exactly what an uninitialized or default-constructed UUID field serializes to, so a stray nil in your data usually means "someone forgot to actually generate one," not "here is a sentinel I chose on purpose." Because it is a real value, using nil as your own "no ID yet" marker is risky — a genuine all-zero UUID (however unlikely to be generated) would be indistinguishable from your placeholder. Prefer a nullable column or an explicit absent state instead.

Generating UUIDs in the browser

Modern browsers and Node expose crypto.randomUUID(), which returns a version 4 UUID from a cryptographically secure source. One catch that surprises people: it is only available in a secure context — HTTPS or localhost. Call it from a plain http:// page and crypto.randomUUID is simply undefined, which is a frequent cause of "works on my machine, breaks on the staging box" bugs. The tools below run entirely in your browser and keep every value local to your device:

Conclusion

A UUID is a 128-bit identifier you can generate anywhere, by anyone, with essentially no coordination. But the version digit and variant digit turn that opaque string into something you can read: v4 for unguessable randomness, v5 for deterministic hashing, v7 when you also need creation-order sorting. Learn to read digit 13, avoid v1's host leakage and v2 entirely, watch for the .NET GUID byte-swap at ecosystem boundaries, and never treat the nil UUID as a safe "empty" sentinel — and UUIDs stop being magic and start being a tool you can reason about.

Frequently Asked Questions

Is a UUID the same as a GUID?

They are the same 128-bit value, and GUID is just Microsoft's name for it. The catch is byte order: Microsoft historically stored the first three fields little-endian, so the identical raw bytes can render as a different string in .NET than in a Java or PostgreSQL library. Exchange the canonical text form, not raw bytes, to stay safe.

How can I tell which version a UUID is?

Read the 13th hex digit — the first character of the third group. It holds the version number directly: 4 is random, 7 is a millisecond-timestamp-prefixed sortable UUID, 5 is a namespaced SHA-1 hash. The 17th digit (8, 9, a, or b) confirms it uses the standard RFC 9562 layout.

Which UUID version should I use?

Use v4 for opaque, unguessable IDs; v7 when you want the IDs to sort in creation order (good for database keys); and v5 when the same input must always produce the same ID. Avoid v1 in new systems because it can embed the generating machine's MAC address and creation time.

Is the all-zeros nil UUID a good "empty" value?

No. The nil UUID (00000000-0000-0000-0000-000000000000) is a legal value and is exactly what an uninitialized field serializes to, so it usually signals a bug rather than an intentional sentinel. Use a nullable column or an explicit absent state instead.

What changed between RFC 4122 and RFC 9562?

RFC 9562 (May 2024) obsoleted RFC 4122 without breaking it: everything old still applies, and it added the time-sortable v6 and v7, the custom v8, and a formal Max UUID. A source that only cites RFC 4122 predates the modern time-ordered formats.