The UUID format
A UUID (Universally Unique Identifier) is a 128-bit value standardized in RFC 4122, printed as 32 hexadecimal digits split by hyphens into five groups: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. All 128 bits are always present, but their meaning depends on the version.
Two of the 128 bits encode the variant (always 10 in binary for RFC 4122 UUIDs). Four bits encode the version number. The remaining 122 bits carry the actual data, whose structure depends on the version.
UUID format:
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
^ ^
| variant bits (always 8, 9, a, or b in the hex char)
version nibble (1, 3, 4, or 5)Versions at a glance
| Version | Method | Key property |
|---|---|---|
| NIL | Fixed (all zeros) | Placeholder / sentinel value |
| v1 | Timestamp + node | Time-sortable, reveals machine info |
| v3 | MD5 hash | Deterministic, same input = same UUID |
| v4 | Random | Most common, no information leakage |
| v5 | SHA-1 hash | Deterministic, preferred over v3 |
NIL: the placeholder UUID
The NIL UUID is a special-case value where all 128 bits are zero. It is not generated by an algorithm. Its purpose is to serve as a sentinel or default value: a UUID-typed field that explicitly carries "nothing assigned yet" without using NULL.
Common uses include default values for optional UUID foreign keys, clearing an ID field, and placeholder values in protocol messages where a UUID field is structurally required but semantically absent.
00000000-0000-0000-0000-000000000000 All 128 bits are zero. Not truly a "version" in the RFC sense. Used as a sentinel, default value, or explicit "no ID assigned."
v1: timestamp-based IDs
v1 encodes the current time as a 60-bit count of 100-nanosecond intervals since October 15, 1582 (the Gregorian calendar reform date used by the OSF DCE standard). The remaining bits hold a 14-bit clock sequence and a 48-bit node identifier, traditionally the MAC address of the generating machine.
Because the timestamp is encoded, v1 UUIDs sort chronologically. Multiple UUIDs generated on the same machine within a single 100ns window are disambiguated by incrementing the clock sequence.
The privacy concern: the MAC address embedded in the node field reveals which machine generated the ID. Modern implementations often substitute a random 48-bit node ID to avoid this, though the timestamp remains recoverable. For new time-sorted ID work, consider ULID or UUID v7 instead.
6ba7b810-9dad-11d1-80b4-00c04fd430c8
^ version nibble = 1
The first three groups (time-low, time-mid, time-high) encode
a 60-bit timestamp counted in 100-nanosecond intervals from
October 15, 1582 (the Gregorian calendar epoch).
The last group is the 48-bit node (MAC address or random).v4: random IDs (the default)
v4 fills all 122 available bits with output from a cryptographically secure pseudorandom number generator (CSPRNG). There is no timestamp, no machine identifier, and no sequential structure. Every v4 UUID is independent of all others.
The collision probability is negligible in practice: generating 1 billion UUIDs per second for 100 years still leaves a collision probability well below 1 in a trillion.
v4 is the right choice for most applications. It has universal library support, leaks no information about the generating system, and requires no configuration.
f47ac10b-58cc-4372-a567-0e02b2c3d479
^ version nibble = 4
550e8400-e29b-41d4-a716-446655440000
^ 122 bits of cryptographically random datav3 and v5: deterministic name-based IDs
v3 and v5 are generated by hashing a namespace UUID concatenated with a name string. v3 uses MD5, v5 uses SHA-1. The same namespace and name always produce the same UUID, on any machine, in any language or library.
RFC 4122 defines four standard namespaces: DNS (for domain names), URL (for URLs), OID (for ISO object identifiers), and X500 (for X.500 distinguished names). You can also generate your own namespace UUID and use it to scope a custom identifier space.
Namespace: DNS (6ba7b810-9dad-11d1-80b4-00c04fd430c8) Name: example.com v3 (MD5): identical UUID on any machine, in any language v5 (SHA-1): identical UUID on any machine, in any language The same namespace + name pair always produces the same UUID. Different namespaces produce different UUIDs even for the same name.
| Namespace | UUID |
|---|---|
| DNS | 6ba7b810-9dad-11d1-80b4-00c04fd430c8 |
| URL | 6ba7b811-9dad-11d1-80b4-00c04fd430c8 |
| OID | 6ba7b812-9dad-11d1-80b4-00c04fd430c8 |
| X500 | 6ba7b814-9dad-11d1-80b4-00c04fd430c8 |
Prefer v5 over v3 for all new work. The SHA-1 foundation is stronger than MD5, and there is no practical reason to choose v3 unless you are matching an existing v3 UUID space.
Which version should you use?
You just need a unique ID and do not require any special properties. This covers 95% of real-world use cases.
You need the same UUID to be generated from the same logical identifier (e.g. a canonical URL, a user email). Use v5 over v3 for new work.
Backward compatibility with an existing v3-based system. Otherwise, prefer v5.
You need time-sortable IDs and are working in a system (e.g. Cassandra) that relies on v1 ordering. Consider ULID or UUID v7 for modern systems.
You need a well-defined "no value" UUID, a default foreign key placeholder, or a sentinel to signal an unset optional identifier.
Frequently asked questions
What happened to UUID v2?
v2 is the DCE Security version defined by the Open Software Foundation. It embeds a POSIX UID or GID along with a timestamp and domain identifier. It was never widely adopted outside of DCE/RPC systems and is considered practically obsolete. Most UUID libraries do not implement it.
What is UUID v6, v7, or v8?
RFC 9562 (published May 2024) defines v6, v7, and v8. v6 is a field-compatible rearrangement of v1 that makes UUIDs time-sortable. v7 encodes a Unix millisecond timestamp in the high bits, similar to ULID but in UUID format, and is the recommended new format for time-ordered IDs. v8 is a custom/vendor-specific version with no defined structure. If you need time-sorted UUIDs on a new project, v7 is worth evaluating.
Can I recover the creation timestamp from a v1 UUID?
Yes. The first three UUID groups encode a 60-bit timestamp in 100-nanosecond intervals since October 15, 1582. You can decode them to get the exact creation time. This is a privacy consideration: anyone with a v1 UUID can determine when and roughly where (which machine) it was generated. Modern implementations often use a random node ID instead of the real MAC address, but the timestamp remains recoverable.
Why are there two name-based versions (v3 and v5)?
v3 uses MD5, which is considered cryptographically broken for security purposes. v5 uses SHA-1, which is stronger. RFC 4122 notes that v5 should be preferred for new work whenever backward compatibility with v3 is not required. In practice, the weakness of MD5 matters very little for UUID generation since UUIDs are not security primitives, but v5 is the safer default.
What is a UUID namespace and why does it matter for v3 and v5?
A namespace is itself a UUID that scopes the name being hashed. The four predefined namespaces (DNS, URL, OID, X500) ensure that a given name produces different UUIDs depending on its intended type. For example, hashing "example.com" under the DNS namespace gives a different UUID than hashing the same string under the URL namespace. You can also define your own namespace UUID for a custom identifier space.
Are v3 and v5 UUIDs secure?
Not in a cryptographic sense. Because they are derived deterministically from inputs, anyone who knows the namespace and name can reproduce the UUID. Do not use v3 or v5 where unpredictability is required, such as session tokens or API keys. For opaque unique identifiers, v4 is the right choice.
Is UUID v4 safe to use as a database primary key?
Yes for correctness. For performance, it depends on scale. v4 UUIDs are random, which causes scattered inserts in B-tree indexes. On write-heavy tables in PostgreSQL or MySQL InnoDB at high volume, this leads to index fragmentation. If this matters for your workload, consider ULID or UUID v7 instead, both of which insert near the tail of the index.