UUIDv7 vs UUIDv4: A Complete Comparison
Understanding the key differences between random UUIDs and time-sortable UUIDs
Universally Unique Identifiers (UUIDs) are 128-bit values used to identify records across distributed systems without coordination. For over a decade, UUIDv4 -- fully random identifiers -- has been the default choice. But in 2024, UUIDv7 emerged as a modern alternative defined in RFC 9562, embedding a Unix timestamp for chronological ordering. Which should you use? Let's compare them across every dimension that matters.
At a Glance
UUIDv4 (Random)
550e8400-e29b-41d4-a716-446655440000
122 random bits. No time component. Uniform random distribution. The standard choice since 2005 (RFC 4122).
UUIDv7 (Time-Sortable)
01936b2e-1e85-7000-8000-4a6f7e3b2c1d
48-bit timestamp + 62 random bits. Chronologically sortable. Defined in RFC 9562 (2024).
Detailed Comparison
| Feature | UUIDv4 | UUIDv7 |
|---|---|---|
| Sortability | Random order | Time-ordered (chronological) |
| Embedded Timestamp | None | 48-bit Unix ms timestamp |
| Random Bits | 122 bits | 62 bits |
| DB Index Performance | Poor (random inserts) | Excellent (sequential inserts) |
| Collision Probability | Extremely low | Extremely low |
| Generation Speed | Fast (random only) | Fast (clock + random) |
| Creation Time Exposure | Hidden (no timestamp) | Visible (ms precision) |
| Standard | RFC 4122 (2005) | RFC 9562 (2024) |
| Ecosystem Support | Universal | Growing rapidly |
Database Performance: Why It Matters
The most impactful difference between UUIDv4 and UUIDv7 is their behavior as database primary keys. Most databases use B-tree indexes for primary keys, and the insertion pattern of UUIDs directly affects index efficiency.
UUIDv4: Random Inserts
- xNew rows land at random positions in the B-tree
- xCauses frequent page splits and index fragmentation
- xPoor cache locality -- recently written pages are evicted
- xWrite performance degrades as table grows
UUIDv7: Sequential Inserts
- +New rows append near the end of the B-tree
- +Minimal page splits, compact index structure
- +Excellent cache locality -- hot pages stay in memory
- +Consistent write performance at scale
Benchmark note: In PostgreSQL benchmarks with 10 million rows, UUIDv7 primary keys typically show 2-3x faster insert throughput compared to UUIDv4, with significantly smaller index sizes due to reduced fragmentation. The gap widens further as table size increases.
Uniqueness and Collision Resistance
UUIDv4 has 122 random bits, which means you would need to generate approximately 2.71 quintillion UUIDs to have a 50% chance of a collision (the birthday paradox). In practical terms, generating 1 billion UUIDs per second would take about 85 years before a collision becomes likely.
UUIDv7 has fewer random bits (62), but its uniqueness model is different. Because UUIDs generated at different milliseconds have different timestamp prefixes, collisions can only occur between UUIDs generated in the same millisecond. With 62 random bits per millisecond window, you would need to generate about 2.15 billion UUIDs in a single millisecond for a 50% collision probability -- far beyond any realistic workload.
Both versions provide more than sufficient uniqueness for any practical application. The theoretical difference in random bits is not a meaningful concern in the real world.
When to Use Each Version
Choose UUIDv7 When...
- Database primary keys -- sequential inserts for B-tree performance
- Event sourcing -- natural chronological ordering of events
- Distributed systems -- time-ordered IDs without coordination
- Audit trails -- creation time embedded in every record
- Time-series data -- sortable IDs that double as rough timestamps
- New projects -- modern default with growing ecosystem support
Choose UUIDv4 When...
- Privacy-sensitive IDs -- creation time must not be inferable
- Security tokens -- maximum entropy with no predictable component
- Existing systems -- already using UUIDv4 with no performance issues
- Platform constraints -- runtime or library lacks UUIDv7 support
- Non-indexed IDs -- IDs not used as database primary keys
Code Examples: Generating Both Versions
// UUIDv4 -- built-in since Node 14+
const v4 = crypto.randomUUID();
// "550e8400-e29b-41d4-a716-446655440000"
// UUIDv7 -- Node.js 20+ or use a library
// npm install uuidv7
import { uuidv7 } from "uuidv7";
const v7 = uuidv7();
// "01936b2e-1e85-7000-8000-4a6f7e3b2c1d"
// Extract timestamp from UUIDv7
function getTimestamp(uuid) {
const hex = uuid.replace(/-/g, "").slice(0, 12);
return new Date(parseInt(hex, 16));
}
console.log(getTimestamp(v7));
// 2024-12-01T10:30:45.000Zimport uuid
# UUIDv4 -- built-in
v4 = uuid.uuid4()
# UUID('550e8400-e29b-41d4-a716-446655440000')
# UUIDv7 -- Python 3.x with uuid7 library
# pip install uuid7
from uuid_extensions import uuid7
v7 = uuid7()
# UUID('01936b2e-1e85-7000-8000-4a6f7e3b2c1d')
# Extract timestamp from UUIDv7
def get_timestamp(uuidv7: str) -> int:
hex_str = str(uuidv7).replace('-', '')[:12]
return int(hex_str, 16)
from datetime import datetime
ts_ms = get_timestamp(str(v7))
print(datetime.utcfromtimestamp(ts_ms / 1000))-- UUIDv4 (all PostgreSQL versions)
SELECT gen_random_uuid();
-- 550e8400-e29b-41d4-a716-446655440000
-- UUIDv7 (PostgreSQL 17+)
SELECT gen_random_uuid_v7();
-- 01936b2e-1e85-7000-8000-4a6f7e3b2c1d
-- Using UUIDv7 as a sortable primary key
CREATE TABLE events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid_v7(),
name TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
-- IDs are naturally ordered by creation timeimport "github.com/google/uuid"
// UUIDv4
v4 := uuid.New()
// UUIDv7
v7, _ := uuid.NewV7()
// Extract timestamp from UUIDv7
ts, _ := uuid.TimestampFromV7(v7)
sec, nsec := ts.Time().Unix(), ts.Time().Nanosecond()Internal Structure Comparison
UUIDv4 Layout (128 bits)
122 random bits + 4-bit version (4) + 2-bit variant
UUIDv7 Layout (128 bits)
48-bit timestamp + 62 random bits + 4-bit version (7) + 2-bit variant
Frequently Asked Questions
Try Our UUID Tools
Extract timestamps from UUIDv7 identifiers or convert Unix timestamps to human-readable dates.