UUID v7: Time-Ordered UUIDs and Why They Beat v4 in Databases
- UUID v7 is a 2024 RFC 9562 standard — it embeds a 48-bit millisecond Unix timestamp in the high bits.
- Because the timestamp is in the high bits, UUID v7 values sort chronologically — newer IDs are always larger.
- UUID v7 solves the B-tree fragmentation problem that UUID v4 causes in relational databases.
- Python 3.12+ has uuid.uuid7() built-in. JavaScript/Node.js needs the uuid library (v9.0+).
Table of Contents
UUID v4 has one big database problem: it's completely random. Every insert goes to a random position in the B-tree index, causing fragmentation, cache misses, and slow writes at scale. UUID v7 fixes this by embedding the current millisecond timestamp in the first 48 bits — so new records always sort after old records, just like auto-increment integers. UUID v7 was standardized in RFC 9562 (May 2024) and is now the recommended UUID format for new database primary keys.
UUID v7 Structure: How the Timestamp Is Embedded
A UUID v7 looks like any other UUID, but the bit layout is different:
018f4e2c-1234-7xxx-yxxx-xxxxxxxxxxxx
^^^^^^^^^^^^
48-bit millisecond Unix timestamp (high bits)
Bit breakdown:
- Bits 0–47 — 48-bit Unix timestamp in milliseconds
- Bits 48–51 — version field, always
0111(7) - Bits 52–63 — 12-bit sequence/random sub-millisecond precision
- Bits 64–65 — variant field, always
10 - Bits 66–127 — random data
Because the timestamp occupies the most significant bits, lexicographic string sort equals chronological order. You can extract the creation time from any UUID v7 value.
UUID v7 vs UUID v4: The Database Performance Difference
The core issue with UUID v4 in relational databases:
- B-tree indexes require inserting new values in the correct sorted position.
- UUID v4 is random, so each insert lands in a random page.
- At scale, most pages are not in the buffer pool — every insert requires a disk read, a page split or shift, and a disk write.
- Result: write amplification, index fragmentation, and poor cache hit rates.
UUID v7 solves this:
- New values are always larger than old values (timestamp-ordered).
- Inserts always append to the right end of the index.
- The active "hot" index page stays in the buffer pool.
- Result: insert performance approaches that of auto-increment integers.
Benchmarks on PostgreSQL with 10M rows show UUID v7 insert performance 2–5x faster than UUID v4, and index size 20–30% smaller due to reduced fragmentation.
Sell Custom Apparel — We Handle Printing & Free ShippingGenerating UUID v7 in Python
Python 3.12+ has native UUID v7 support:
import uuid
# Python 3.12+
uid = uuid.uuid7()
print(uid) # "018f4e2c-1234-7abc-8def-1234567890ab"
# Extract timestamp from UUID v7
import datetime
ts_ms = (uid.int >> 80) & 0xFFFFFFFFFFFF
dt = datetime.datetime.fromtimestamp(ts_ms / 1000, tz=datetime.timezone.utc)
print(dt) # "2026-04-14 12:34:56.789+00:00"
For Python 3.11 and below, use the uuid7 PyPI package:
pip install uuid7
import uuid_extensions
uid = uuid_extensions.uuid7()
print(str(uid))
Generating UUID v7 in JavaScript and Node.js
The uuid npm package added v7 support in version 9.0:
npm install uuid
import { v7 as uuidv7 } from 'uuid';
const id = uuidv7();
console.log(id); // "018f4e2c-1234-7abc-8def-1234567890ab"
// Multiple IDs are guaranteed to be monotonically increasing
// even within the same millisecond
const ids = Array.from({ length: 5 }, () => uuidv7());
console.log(ids.every((id, i) => i === 0 || ids[i-1] < id)); // true
In Node.js 21+, crypto.randomUUID() still generates UUID v4. For UUID v7 in native Node.js, the uuid package is the standard choice.
Using UUID v7 as a Database Primary Key
UUID v7 is a drop-in replacement for UUID v4 in any database — the format is identical (36 chars, same regex). Just switch the generation function:
-- PostgreSQL: no change needed — store as UUID type
-- Generate in application code, insert as usual
-- Check chronological order of UUID v7 values:
SELECT id, created_at
FROM orders
ORDER BY id; -- orders by insertion time, same as ORDER BY created_at
For PostgreSQL, there's no native gen_random_uuidv7() yet, but the pg_uuidv7 extension adds it. Most teams generate UUID v7 in application code and insert normally.
UUID v7 vs ULID: both are time-ordered sortable IDs. UUID v7 has the advantage of fitting anywhere UUID v4 is expected (same format). ULID uses a different alphabet and doesn't fit UUID columns without conversion.
Generate UUID v4 Values While UUID v7 Support Rolls Out
The Cheetah UUID Generator produces RFC-compliant UUID v4 strings — useful for testing, Postman collections, or any system that hasn't adopted UUID v7 yet.
Open Free UUID GeneratorFrequently Asked Questions
Is UUID v7 backwards compatible with UUID v4?
Yes, as a format. UUID v7 values are 36-character hyphenated strings, pass UUID regex validation, and fit in any UUID column. Applications that don't inspect the version nibble won't know the difference.
Can I extract the creation timestamp from a UUID v7?
Yes. The first 48 bits are the Unix millisecond timestamp. Shift right by 80 bits and you have the timestamp. Most UUID v7 libraries provide a helper function for this.
Does UUID v7 leak the creation time?
Yes — the timestamp is embedded in the UUID. If your IDs are public-facing and you don't want to reveal creation times, UUID v4 is the better choice.
Is UUID v7 the same as ULID?
Both are time-ordered sortable IDs with similar goals. Key differences: UUID v7 uses standard UUID format (fits existing UUID columns), ULID uses Crockford base32 (more compact but not UUID-compatible). UUID v7 is an official RFC standard; ULID is a community spec.

