Choosing an identifier scheme for a distributed system feels straightforward until database performance degrades under scale. For more than two decades, software teams defaulted to UUID v4 for generating unique primary keys across decoupled microservices. While random keys eliminate coordination between application servers, they introduce hidden costs when indexed inside relational database engines.
IETF RFC 9562 updated the standard by introducing time-ordered formats like UUID v7. This resolves the long-standing conflict between decentralized key creation and sequential database storage. Knowing how UUID v1, v4, and v7 differ in layout, entropy, and index behavior helps you choose the right identifier for your architecture.
UUID version comparison: Technical specifications
| Feature | UUID v1 | UUID v4 | UUID v7 |
|---|---|---|---|
| Standard Specification | RFC 4122 (Legacy) | RFC 4122 & RFC 9562 | RFC 9562 (Modern Standard) |
| Bit Composition | 60-bit timestamp, 14-bit clock sequence, 48-bit MAC address | 122 bits cryptographically secure pseudo-random entropy | 48-bit Unix epoch timestamp, 74 bits entropy and sequence counter |
| Sortability | Broken without custom byte reordering | Non-sortable (entirely random distribution) | Naturally sortable lexicographically and chronologically |
| B-Tree Index Impact | High fragmentation without custom reordering | Severe index fragmentation and frequent page splits | Optimal sequential inserts with minimal page splits |
| Privacy & Security | Low (exposes host MAC address and generation timestamp) | High (fully opaque random values) | Moderate (exposes creation timestamp down to millisecond precision) |
| Primary Application | Legacy distributed databases (e.g., historical Cassandra schemas) | Ephemeral session tokens, public opaque links, non-indexed keys | Relational database primary keys, event logs, partitioned tables |
Every identifier standard balances predictability, entropy, and storage locality. UUID v4 prioritizes complete randomness, making each identifier impossible to guess from prior values. However, that randomness scatters inserts unpredictably across storage pages. UUID v7 introduces millisecond-precision timestamps into the leading bits, creating a natural sort order while retaining 74 bits of entropy to prevent collisions across distributed workers.
When to choose each UUID version
Use UUID v7 for database primary keys and clustered indexes
Relational databases like PostgreSQL, MySQL InnoDB, and SQLite organize primary key indexes using B-trees. When new rows arrive with completely random keys, the database engine must insert leaf nodes into random physical pages on disk. If a target page is full, the engine performs a page split, allocating a new 8KB or 16KB block and copying half the existing rows into it.
This process causes two compounding issues:
- Disk write amplification, where small row inserts force full disk block rewrites.
- Low index page fill factors, leaving indexes half empty and bloating memory usage in buffer pools.
UUID v7 addresses this problem by placing a 48-bit millisecond Unix timestamp at the beginning of the identifier. Because new records always carry equal or increasing timestamps, database storage engines insert rows into the rightmost leaf pages. This sequential append behavior maintains high index density and dramatically reduces page cache misses.
Use UUID v4 for opaque public tokens and non-indexed keys
Not every identifier belongs in a clustered index. When generating password reset tokens, checkout session IDs, or shareable external links, predictability is a security vulnerability.
Because UUID v7 encodes a readable creation timestamp, an observer can inspect consecutive identifiers to estimate account registration rates, order volume, or internal activity spikes. UUID v4 contains 122 bits of cryptographically generated entropy with zero timing metadata. If you need public identifiers where internal generation patterns must remain hidden—similar to how you might decode and inspect JWT tokens safely to verify claims without exposing secrets—UUID v4 remains the correct choice.
Why UUID v1 should be avoided in modern architectures
UUID v1 was designed when distributed nodes lacked reliable synchronization mechanisms. It relied on two components: a 60-bit Gregorian timestamp and the 48-bit hardware MAC address of the network interface card.
This design introduces two critical flaws:
- Security and privacy leakage: Any party reading a UUID v1 value can extract the exact physical MAC address of the server, exposing internal network infrastructure details to potential attackers.
- Unnatural byte ordering: The specification split the timestamp into low, mid, and high fields, with low bits appearing first. As a result, standard alphabetical sorting does not match chronological creation order unless custom byte-swapping functions are applied.
Aside from maintaining backwards compatibility with legacy databases, UUID v1 offers no advantage over modern alternatives.
Decision matrix for identifier selection
To select the appropriate version for your implementation, evaluate these functional requirements:
| System Requirement | Recommended Version | Primary Rationale |
|---|---|---|
| Clustered primary key in B-tree database | UUID v7 | Preserves index locality and prevents page splits |
| Public token, API secret, or reset link | UUID v4 | Hides timing metadata and prevents enumeration attacks |
| Distributed event streaming or audit log | UUID v7 | Enables time-based range queries and natural sorting |
| Non-indexed unique constraint validation | UUID v4 | Maximum entropy with zero time-based correlation |
| Legacy Cassandra or historical schema | UUID v1 | Matches older database driver expectations |
Practical testing and implementation
Modern programming environments and database systems increasingly provide native tools for generating and parsing RFC 9562 identifiers. For example, recent releases of PostgreSQL and runtime ecosystems provide direct helper functions for v7 generation.
When developing and prototyping schemas locally, testing sample records helps verify whether sorting rules and index layouts behave as expected. You can test generation rules using the UUID Generator to inspect UUID v1, v4, and v7 formats directly within your browser. Because processing runs entirely on client hardware through the Web Crypto API, unique keys are generated instantly without sending payloads across external network connections.
When integrating identifiers into production application code:
- Store identifiers in native 16-byte binary columns (such as UUID in PostgreSQL or BINARY(16) in MySQL) rather than 36-character string representations to cut storage requirements in half.
- Use cryptographically secure entropy sources like crypto.getRandomValues() or system urandom instead of deterministic pseudo-random generators to avoid duplicate collisions across concurrent processes.
- Validate version bytes when receiving external inputs to prevent mixing random v4 keys into v7 sequential tables.