UUID Versions
A practical guide to UUID versions.
UUID Versions: A Practical Guide of why it matters
A Universally Unique Identifier (UUID) is a 128-bit label used to uniquely identify information in computer systems without requiring a central coordinating authority. UUIDs are standardized by RFC 9562 (which obsoleted RFC 4122 in May 2024) and ISO/IEC 9834-8.
They matter because in modern distributed systems you often need to generate identifiers:
- Independently across many nodes (no central sequence generator),
- Without collisions (statistically negligible probability),
- Sometimes with ordering / locality properties (critical for database index performance).
The version you choose has direct implications on insert performance, index fragmentation, privacy, and sortability.
UUID Versions Overview
| Version | What It Does | Reference |
|---|---|---|
| v1 - Time-based (Gregorian timestamp + MAC address) | Combines a 60-bit timestamp (100-ns intervals since 1582-10-15) with a clock sequence and the node’s MAC address. Sortable by time, but leaks the host’s MAC address (privacy concern). | RFC 9562 §5.1 |
| v2 - DCE Security | Similar to v1 but replaces parts of the timestamp/clock-seq with a POSIX UID/GID. Rarely used outside DCE; not recommended for general purpose. | RFC 9562 §5.2 / DCE 1.1 Authentication |
| v3 - Name-based (MD5 hash) | Deterministically derived by MD5-hashing a namespace UUID + a name. Same input → same UUID. Useful for reproducible IDs; MD5 is cryptographically weak so prefer v5 if security matters. | RFC 9562 §5.3 |
| v4 - Random | 122 bits of (cryptographically) random data. No ordering, no metadata leaked. The most common UUID in web apps and APIs. Collision probability is astronomically low. | RFC 9562 §5.4 |
| v5 - Name-based (SHA-1 hash) | Same idea as v3 but uses SHA-1. Preferred over v3 for deterministic IDs from namespaces (e.g., URLs, DNS names). | RFC 9562 §5.5 |
| v6 - Reordered Time-based | Re-orders the v1 timestamp fields so the most-significant bits are the most-significant of the timestamp. Result: lexicographically sortable while remaining backwards-compatible with v1 semantics. | RFC 9562 §5.6 |
| v7 - Unix Epoch Time-based | 48-bit Unix millisecond timestamp + 74 bits of random data. Sortable by creation time, no MAC leak, excellent for database primary keys. The recommended modern choice for new systems needing time-ordering. | RFC 9562 §5.7 |
| v8 - Custom/Experimental | A free-form vendor/application-defined layout (only the version & variant bits are fixed). Intended for experimentation or domain-specific schemes (e.g., embedding shard IDs). | RFC 9562 §5.8 |
| Nil UUID | All-zero UUID (00000000-0000-0000-0000-000000000000). Used as a sentinel/placeholder value. | RFC 9562 §5.9 |
| Max UUID | All-ones UUID (ffffffff-ffff-ffff-ffff-ffffffffffff). Useful as an upper-bound sentinel in range queries. | RFC 9562 §5.10 |
Note: Versions 6, 7, and 8 were introduced by RFC 9562 (May 2024). Earlier RFC 4122 (2005) only defined v1–v5.
UUID v4 vs v7 - and Why It Matters
This is the most important practical comparison for anyone designing a database schema or a distributed identifier strategy today.
Side-by-side
| Aspect | UUID v4 | UUID v7 |
|---|---|---|
| Bit layout | 122 bits random + 6 fixed bits | 48-bit Unix ms timestamp + 74 bits random + 6 fixed bits |
| Sortable by creation time? | ❌ No (purely random) | ✅ Yes (lexicographic order ≈ chronological order) |
| Reveals creation time? | No | Yes (millisecond precision) |
| Reveals host info (MAC, etc.)? | No | No |
| Collision resistance | Excellent (~2¹²² entropy) | Very good (~2⁷⁴ entropy per millisecond) |
| B-Tree index locality | Poor - random inserts scatter across the index | Excellent - new rows append near the tail of the index |
| Suitable as DB primary key? | Workable but suboptimal at scale | Strongly recommended |
| Standardized | RFC 4122 (2005) & RFC 9562 (2024) | RFC 9562 (2024) |
Why this matters in practice
Database performance (the big one). Most relational databases (PostgreSQL, MySQL/InnoDB, SQL Server) store table rows or index entries in a B-Tree ordered by the primary key. With v4, every
INSERTlands at a random position in the index, causing:- Frequent page splits,
- Cache misses (the relevant index pages are rarely in memory),
- Index fragmentation and bloat,
- Worse write throughput as the table grows.
With v7, inserts are monotonically increasing, so new rows almost always go to the rightmost leaf of the B-Tree - similar performance characteristics to an auto-increment integer, but without the central coordination. This is well-documented; e.g., the PostgreSQL community discussion of UUIDv7 (wiki.postgresql.org - UUIDv7) and Buildkite’s analysis (Goodbye integers, hello UUIDv7) both demonstrate large reductions in index size and write latency when migrating from v4 to v7.
Pagination and range queries. With v7 you can do
WHERE id > :last_id ORDER BY idto paginate roughly by creation time without an extracreated_atcolumn. Not possible with v4.Debuggability and operability. v7 IDs encode “when was this created?” - extremely useful in logs, support tickets, and forensic analysis. v4 tells you nothing.
Privacy trade-off. v7 leaks the creation timestamp. For most internal systems and primary keys this is fine (and often desirable). For user-facing public tokens (password reset links, share URLs, API keys), prefer v4 so you don’t reveal when something was issued. Don’t use either as a security secret on their own.
Distributed generation. Both v4 and v7 can be generated independently on any node with no coordination. v7 keeps that property and gives you rough global ordering - the best of both worlds for microservice architectures.
Rule of thumb
| Use case | Recommended |
|---|---|
| Primary key in a relational DB | v7 |
| Sortable event/log IDs | v7 |
| Public-facing opaque tokens / share links / reset codes | v4 |
| Deterministic IDs derived from a name (e.g., a URL) | v5 |
| Need to embed a shard ID, tenant ID, or other custom layout | v8 |
| Legacy interoperability with pre-2024 systems | v4 (universally supported) |
Key References
- RFC 9562 - Universally Unique IDentifiers (UUIDs), May 2024 - https://www.rfc-editor.org/rfc/rfc9562
- RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace, 2005 (obsoleted by 9562) - https://www.rfc-editor.org/rfc/rfc4122
- ITU-T X.667 / ISO/IEC 9834-8 - Generation and registration of UUIDs - https://www.itu.int/rec/T-REC-X.667
- PostgreSQL Wiki - UUIDv7 - https://wiki.postgresql.org/wiki/UUIDv7
- Buildkite Engineering - Goodbye integers, hello UUIDv7 - https://buildkite.com/blog/goodbye-integers-hello-uuids
A word about me

Hi, I'm Sashitha. In my blog, I break down topics that interest me into simple, digestible bits, the way I would explain them to myself when I was first trying to figure things out.
A big part of how I learn is by framing technical concepts as narratives to make them easier to understand and remember.
My goal in writing these blogs is to deepen my own understanding and hopefully help others learn along the way and apply these concepts to solve real-world problems. Feedback is always welcome, so feel free to reach out.