UUIDs are everywhere. Database primary keys, API request IDs, session tokens, distributed system identifiers — if you've written backend code, you've generated millions of them.
But here's a question most developers never stop to ask: which UUID version should I actually be using?
For years, UUID v4 was the default answer. Random bytes, good enough, move on. But UUID v7 landed in RFC 9562 (May 2024) and it changes the game in ways that matter for real-world systems.
Let's break it down.
UUID v4: The Random Standard
UUID v4 is pure randomness. 122 random bits, 6 bits for version and variant metadata. That's it.
f47ac10b-58cc-4372-a567-0d8b62691e10
^^^^
version 4
How it works:
- Generate 128 random bits
- Set version (4 bits →
0100) - Set variant (2 bits →
10) - Format as 8-4-4-4-12 hex string
The good:
- Dead simple to generate
- Statistically unique (2^122 possible values)
- No coordination needed between systems
- No information leakage (no timestamps, no MAC addresses)
The not-so-good:
- Completely random = terrible for database indexing
- No natural ordering
- Can't extract any useful metadata
- B-tree index fragmentation in databases
UUID v4 has served us well. But "good enough" isn't the same as "optimal."
UUID v7: Time-Ordered by Design
UUID v7 is the new kid, and it was designed specifically to fix v4's biggest weakness: sort order.
019526de-a3c0-7cc0-b2e8-4a1b3c5d7e9f
^^^^^^^^ ^^^^
timestamp version 7
How it works:
- Take the current Unix timestamp in milliseconds (48 bits)
- Set version (4 bits →
0111) - Set variant (2 bits →
10) - Fill remaining 62 bits with random data
- Format as standard UUID string
The structure:
| 48 bits | 4 | 12 bits | 2 | 62 bits |
| timestamp |ver| rand_a |var| rand_b |
The good:
- Naturally time-ordered (lexicographic sort = chronological sort)
- Database-friendly: sequential inserts, minimal B-tree page splits
- Timestamp extractable: you can read when the UUID was created
- Still globally unique (62 random bits + millisecond timestamp)
- Drop-in replacement: same 128-bit, same string format
The trade-offs:
- Leaks creation time (the first 48 bits ARE the timestamp)
- Slightly less randomness than v4 (62 vs 122 random bits)
- Newer — not all libraries support it yet
The Database Performance Story
This is where UUID v7 really shines, and why it was created in the first place.
The Problem with v4 in Databases
When you use UUID v4 as a primary key in a B-tree indexed table (which is... most tables), every INSERT goes to a random location in the index. This causes:
- Page splits: The B-tree constantly reorganizes
- Cache misses: No locality of reference
- Write amplification: More I/O per insert
- Index bloat: Fragmented pages with wasted space
At scale, this matters. A lot.
How v7 Fixes It
Because UUID v7 values are time-ordered, new inserts always go to the end of the B-tree. This means:
- Sequential writes: Appending, not random inserting
- Better cache utilization: Recent data is co-located
- Fewer page splits: The tree grows naturally
- Smaller indexes: Less fragmentation
Benchmarks consistently show 2-10x better INSERT performance with UUID v7 vs v4 on PostgreSQL and MySQL, depending on table size and workload.
When to Use Which
Use UUID v4 when:
- You need zero information leakage (timestamps are sensitive)
- You're generating tokens or secrets (maximum entropy matters)
- Ordering doesn't matter (in-memory lookups, hash maps)
- You're working with systems that only support v4
Use UUID v7 when:
- IDs are database primary keys (the main use case)
- You want natural chronological ordering
- You need to extract creation time from the ID
- You're building distributed systems that need time-ordered events
- You care about database performance at scale
Quick Decision Matrix
| Scenario | Recommendation |
|---|---|
| Database primary key | v7 |
| API request tracing | v7 |
| Session tokens | v4 |
| Event sourcing | v7 |
| Password reset tokens | v4 |
| Distributed log entries | v7 |
| Cache keys (no ordering needed) | v4 |
Extracting the Timestamp from v7
One of v7's underrated features: you can read the creation time directly from the UUID.
function extractTimestamp(uuidV7) {
const hex = uuidV7.replace(/-/g, '');
const timestampHex = hex.substring(0, 12);
const timestampMs = parseInt(timestampHex, 16);
return new Date(timestampMs);
}
// Example
extractTimestamp('019526de-a3c0-7cc0-b2e8-4a1b3c5d7e9f');
// → 2025-02-05T...
This is incredibly useful for debugging, auditing, and understanding data flow without extra columns or metadata.
Generating UUIDs in Practice
Node.js (v20+):
import { randomUUID } from 'crypto';
// v4 only (as of Node 22)
const id = randomUUID();
// For v7, use a library:
import { v7 as uuidv7 } from 'uuid';
const id = uuidv7();
Python:
import uuid
# v4
uuid.uuid4()
# v7 (Python 3.14+ or uuid7 package)
from uuid_extensions import uuid7
uuid7()
PostgreSQL:
-- v4 (built-in)
SELECT gen_random_uuid();
-- v7 (PostgreSQL 17+ or pg_uuidv7 extension)
SELECT uuid_generate_v7();
Or just use a free online tool: createuuid.com — generates v1, v4, and v7 UUIDs instantly in your browser, with bulk generation support.
The Migration Question
"Should I migrate my existing v4 columns to v7?"
Short answer: probably not.
Existing v4 UUIDs work fine. The cost of migrating primary keys in production databases is almost never worth it. Instead:
- Use v7 for new tables and services
- Keep v4 where it already exists
- Let the natural lifecycle of your system handle the transition
The one exception: if you're experiencing real performance issues from UUID v4 index fragmentation at scale, and you've confirmed UUIDs are the bottleneck (not something else), then a planned migration might be worth it.
TL;DR
| UUID v4 | UUID v7 | |
|---|---|---|
| Introduced | RFC 4122 (2005) | RFC 9562 (2024) |
| Random bits | 122 | 62 |
| Time-ordered | ❌ | ✅ |
| DB performance | Poor at scale | Excellent |
| Timestamp readable | ❌ | ✅ |
| Best for | Tokens, secrets | Primary keys, events |
UUID v7 isn't a replacement for v4 — it's the right tool for a different (and very common) job. If you're starting a new project and your UUIDs will be database primary keys, v7 is the better default.
Need to generate some UUIDs right now? Try createuuid.com — free, instant, no signup.
This is part of the Developer Tools Deep Dives series, where we explain the concepts behind common developer utilities.
Top comments (0)