20 min read

UUID Versions

A practical guide to UUID versions.

distributed systems uuid databases

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

VersionWhat It DoesReference
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 SecuritySimilar 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 - Random122 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-basedRe-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-based48-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/ExperimentalA 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 UUIDAll-zero UUID (00000000-0000-0000-0000-000000000000). Used as a sentinel/placeholder value.RFC 9562 §5.9
Max UUIDAll-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

AspectUUID v4UUID v7
Bit layout122 bits random + 6 fixed bits48-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?NoYes (millisecond precision)
Reveals host info (MAC, etc.)?NoNo
Collision resistanceExcellent (~2¹²² entropy)Very good (~2⁷⁴ entropy per millisecond)
B-Tree index localityPoor - random inserts scatter across the indexExcellent - new rows append near the tail of the index
Suitable as DB primary key?Workable but suboptimal at scaleStrongly recommended
StandardizedRFC 4122 (2005) & RFC 9562 (2024)RFC 9562 (2024)

Why this matters in practice

  1. 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 INSERT lands 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.

  2. Pagination and range queries. With v7 you can do WHERE id > :last_id ORDER BY id to paginate roughly by creation time without an extra created_at column. Not possible with v4.

  3. Debuggability and operability. v7 IDs encode “when was this created?” - extremely useful in logs, support tickets, and forensic analysis. v4 tells you nothing.

  4. 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.

  5. 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 caseRecommended
Primary key in a relational DBv7
Sortable event/log IDsv7
Public-facing opaque tokens / share links / reset codesv4
Deterministic IDs derived from a name (e.g., a URL)v5
Need to embed a shard ID, tenant ID, or other custom layoutv8
Legacy interoperability with pre-2024 systemsv4 (universally supported)

Key References

A word about me

Sashitha Fonseka

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.