Skip to content
SimpleTools24

UUID v3 vs v5: Name-Based UUIDs Explained

By SimpleTools24Published 3 min read

UUID v3 and v5 are name-based: they combine a namespace UUID with a name, such as a domain or URL, and hash them to produce a UUID. The same namespace and name always give the same UUID, which makes them useful for stable, reproducible IDs. The difference is the hash: v3 uses MD5 and v5 uses SHA-1. RFC 9562 recommends v5 over v3, and both are preferable to inventing your own scheme. Neither hides the input if someone can guess it.

How Name-Based UUIDs Work

  1. Pick a namespace UUID, either a standard one or your own.
  2. Take the name as bytes (usually UTF-8 text).
  3. Hash the namespace bytes followed by the name bytes: MD5 for v3, SHA-1 for v5.
  4. Take the first 128 bits of the hash, then set the version (3 or 5) and variant bits.

Example in Python:

python
import uuid

uuid.uuid5(uuid.NAMESPACE_DNS, 'example.com')
# UUID('cfbff0d1-9375-5685-968c-48ce8b15ae17')  -- same result every time

uuid.uuid3(uuid.NAMESPACE_DNS, 'example.com')
# UUID('9073926b-929f-31c2-abc9-fad77ae3e8eb')

Run it anywhere, on any machine, and you get the same values.

Standard Namespaces

RFC 9562 lists predefined namespace UUIDs for common kinds of names:

Predefined namespace UUIDs
NamespaceUUIDUse for
DNS6ba7b810-9dad-11d1-80b4-00c04fd430c8Domain names
URL6ba7b811-9dad-11d1-80b4-00c04fd430c8URLs
OID6ba7b812-9dad-11d1-80b4-00c04fd430c8ISO object identifiers
X.5006ba7b814-9dad-11d1-80b4-00c04fd430c8X.500 distinguished names

For your own data, generate one random UUID to serve as your application's namespace, store it in configuration, and use it consistently. Mixing namespaces produces different UUIDs for the same name.

v3 vs v5 Side by Side

UUID v3 and v5 compared
UUID v3UUID v5
HashMD5SHA-1
Bits from hash128 of 128 (6 overwritten)128 of 160 (6 overwritten)
RecommendationLegacy compatibilityPreferred
DeterministicYesYes
SecurityNot a security featureNot a security feature

MD5 and SHA-1 both have known weaknesses as cryptographic hashes, but here they're used for distribution and determinism, not secrecy. Still, the RFC prefers SHA-1 (v5) and allows v8 for designs needing a modern hash such as SHA-256.

Good Uses for Name-Based UUIDs

  • Stable IDs from natural keys: the same email, URL or product code always maps to the same UUID across services, without a lookup table.
  • Idempotent imports: re-running an import produces the same IDs, so duplicates are easy to detect.
  • Deduplicating URLs or resources: hash the canonical URL under the URL namespace.
  • Cross-system references: two services can independently derive the same ID for the same entity.

Caveats

  • Not secret. If someone can guess the name, they can compute the UUID. Don't use v3 or v5 to hide email addresses or other personal data.
  • Not reversible, but guessable. You can't get the name back from the UUID; you can only test guesses.
  • Input normalisation matters. Example.com and example.com, or URLs with and without a trailing slash, give different UUIDs. Normalise names before hashing.
  • Collisions. Different names producing the same UUID are theoretically possible but not a practical concern for normal use.

Identifying v3 and v5 UUIDs

The 13th hex digit is 3 or 5. In cfbff0d1-9375-5685-968c-48ce8b15ae17, the third group starts with 5, so it's v5. How to tell which version a UUID is explains the version and variant digits.

The UUID decoder identifies name-based UUIDs and their variant. It can't recover the original name, because the hash is one-way; to check a guess, generate the UUID from that namespace and name and compare. The GUID generator can create v3 and v5 values from a namespace and name, and UUID versions explained places them alongside the other versions. In Python, see how to generate a UUID in Python.

Choosing and Managing Your Own Namespace

For application data, create your own namespace UUID once:

python
import uuid
APP_NAMESPACE = uuid.UUID('3d6f0a2c-8b4e-4f1a-9c7d-5e2b1a0f9c84')  # generated once, then fixed

def customer_uuid(email: str) -> uuid.UUID:
    return uuid.uuid5(APP_NAMESPACE, email.strip().lower())

Keep the namespace in configuration or code, never regenerate it, and document it. Changing it later changes every derived ID.

Name-Based IDs and Privacy

Because anyone with the namespace can recompute the UUID from a guessed name, a v5 UUID derived from an email address effectively identifies that person to anyone who knows the namespace and suspects the email. Don't treat it as anonymised data. If you need pseudonymous IDs, use a keyed hash (such as HMAC) with a secret key, or random IDs stored in a lookup table.

Frequently Asked Questions

Is UUID v5 random?

No. It's deterministic: the same namespace and name always produce the same UUID.

Can I get the original name from a v5 UUID?

No. You can only test guesses by generating UUIDs and comparing.

Should I use v3 or v5?

v5, unless you need compatibility with an existing v3 system.

Can I use my own namespace?

Yes. Generate a random UUID once and use it as your application's namespace.

Summary

v3 and v5 deterministically hash a namespace and name into a UUID. Prefer v5, normalise names before hashing, use your own namespace for your data, and never treat them as a way to hide information.

Sources