UUIDv5 Explained: Deterministic Namespace UUIDs from a Name and SHA-1
How UUIDv5 hashes a namespace UUID plus a name with SHA-1 to make deterministic, idempotent IDs, why the same input always yields the same UUID, and how it differs from random v4.
UUIDv5 Explained: Deterministic Namespace UUIDs from a Name and SHA-1
Most UUIDs you see are version 4: 128 bits of randomness with no meaning behind them. They are great when you need an ID that nobody can guess and that will almost never collide. But randomness has a cost. Once a v4 UUID is minted, the only way to find it again is to write it down somewhere. There is no path back from the data to the ID.
UUIDv5 takes the opposite approach. Instead of rolling dice, it derives the UUID from inputs you already have, so the same data always produces the same identifier. That single property changes how you can use IDs across systems, and it is worth understanding before you reach for v4 out of habit.
What v5 actually computes
A v5 UUID is the SHA-1 hash of two things concatenated together: a namespace UUID and a name.
The recipe is precise. Take the 16 raw bytes of the namespace UUID, append the UTF-8 bytes of the name, and run SHA-1 over the whole buffer. SHA-1 returns 20 bytes; you keep the first 16. Then you overwrite two small fields: the four version bits get set to 0101 (the number 5), and the top two bits of the variant byte get set to the RFC layout. What comes out is a perfectly normal-looking UUID — eight-four-four-four-twelve hex digits — that happens to be a fingerprint of its inputs.
The concrete claim that makes v5 useful: because the output is a pure function of the namespace bytes and the name bytes, the same namespace and the same name always produce the identical UUID, on any machine, in any programming language, today or in ten years. There is no clock reading and no random source anywhere in the calculation. This is what people mean when they call v5 ids idempotent — you can compute the ID over and over and get the same answer every time.
A worked example
Let me make this concrete with the canonical case.
RFC 4122 defines a fixed namespace for domain names, the DNS namespace, whose UUID is the constant 6ba7b810-9dad-11d1-80b4-00c04fd430c8. Suppose the name you want to hash is the host example.com.
The tool concatenates the 16 bytes of that namespace UUID with the UTF-8 bytes of example.com, hashes the result with SHA-1, truncates to 16 bytes, and stamps the version and variant bits. The answer is:
cfbff0d1-9375-5685-968c-48ce8b15ae17
Notice the 5 at the start of the third group — that is the version nibble, telling any reader this is a v5 UUID. Now the important part: type the exact same namespace and the exact same name into any conforming library on the planet and you get cfbff0d1-9375-5685-968c-48ce8b15ae17 back. Two engineers on opposite sides of the world, never having spoken, will agree on this ID without exchanging a single byte. You can confirm it yourself in the UUIDv5 Generator, which ships the four standard namespaces as presets so you do not have to memorize the constants.
Why the namespace matters
You might wonder why v5 bothers with a namespace at all. Why not just hash the name?
Because names collide across contexts. Imagine you hash the bare string example.com. In one system it is a DNS host; in another it is, by coincidence, a product code or a folder name. Hash the name alone and those two unrelated things land on the same UUID. The namespace is the fix: it is a fixed UUID prepended to every name in one family, so the DNS host example.com and the product code example.com get distinct IDs because they sit in distinct namespaces.
RFC 4122 ships four well-known namespaces for the common cases — DNS, URL, OID, and X.500 — but you are not limited to them. Generate any random UUID once, write it down, and reuse it as the namespace for a whole family of your own IDs. That random UUID becomes the private prefix that keeps your derived IDs from ever clashing with anyone else's.
v5 versus v4: when to use which
These two versions answer different questions, and choosing wrong is a common mistake.
Reach for v4 when you need uniqueness and unpredictability: session tokens, API keys, anything where being guessable is a security flaw. A v4 ID carries no information about its input precisely because there is no input. If you need that, the plain UUID Generator mints random v4 values on demand.
Reach for v5 when you want a stable ID derived from existing data. The classic case is content-addressing: derive a cache key from a document's canonical URL, and any worker that knows the URL can recompute the key and find the entry without consulting a shared lookup table. Or deduplicate records arriving from two feeds keyed by email — compute uuidV5(email, namespace) on both sides and the rows collapse to one ID with no fuzzy matching. The whole point is that you never have to store the ID, because you can always recompute it.
A warning that follows directly from this: a v5 UUID is not a secret. Anyone who knows your namespace and your naming scheme can regenerate every ID you have. That is exactly what makes it reproducible, and exactly why it is wrong for tokens that must stay unpredictable.
A note on SHA-1
People sometimes flinch at SHA-1, since it has been broken for digital signatures — attackers can craft two different documents that hash to the same value. Does that disqualify it here?
In my own work I treated this with suspicion at first, then realized the threat model simply does not apply. A v5 UUID needs a stable, well-distributed mapping from input to output, not collision resistance against a funded adversary. The name you hash is not a secret, and the UUID is an identifier, not a security token, so there is no document for an attacker to forge into a matching hash. RFC 4122 itself specifies SHA-1 for v5, which means every conforming library produces exactly the same values — and that interoperability is worth more than swapping in a newer hash that would break compatibility with the rest of the world.
One real trap: encoding
The single failure mode I see most often is a name encoding mismatch. v5 hashes the UTF-8 bytes of the name. If one system encodes the name as UTF-16, or leaves stray leading whitespace, or normalizes Unicode differently, the bytes differ and so does the UUID — even though the two strings look identical on screen. The IDs silently stop matching, and you chase a phantom bug for an afternoon. Normalize and trim the name to exactly the same bytes everywhere you compute it, and the determinism that makes v5 valuable will hold.
That is the whole story. v5 trades v4's unpredictability for reproducibility: feed it a namespace and a name, get back an ID you can always regenerate from the same inputs. Once that clicks, a lot of "store the random ID in a table" problems just disappear.
Made by Toolora · Updated 2026-06-13