UUID v7-Generator

Generieren Sie RFC 9562 UUID v7-Identifikatoren mit zeitlicher Sortierung und hoher Entropie

What is a UUID v7?

UUID version 7 is a time-ordered unique identifier introduced in RFC 9562 (2024), designed specifically for use as database primary keys and distributed system identifiers where chronological sorting matters. Unlike UUID v4 which fills all available bits with random data, UUID v7 encodes a Unix timestamp in milliseconds in the most significant 48 bits, followed by random data in the remaining bits. This produces identifiers that are both globally unique and naturally sortable by creation time β€” a property that dramatically improves B-tree index performance in relational databases.

The format follows the standard UUID structure: xxxxxxxx-xxxx-7xxx-yxxx-xxxxxxxxxxxx, where the "7" indicates version 7 and "y" is one of 8, 9, a, or b (the RFC 9562 variant bits). When you generate multiple v7 UUIDs, they sort lexicographically in the same order they were created β€” no additional timestamp column or secondary index is required to establish ordering.

Time-Ordering and Monotonicity

The defining feature of UUID v7 is its monotonic time-ordering. The first 48 bits store a Unix timestamp in milliseconds (sufficient until the year 10889), which means UUIDs generated later always have a higher numeric value than those generated earlier. Within the same millisecond, the remaining random bits provide sub-millisecond uniqueness while preserving approximate ordering.

RFC 9562 Section 6.2 recommends optional monotonic counter techniques for implementations that generate multiple UUIDs within the same millisecond. A counter or random increment can be placed in bits 12–62 (the "rand_a" and part of "rand_b" fields) to guarantee strict ordering even under high-throughput generation. This tool uses cryptographic randomness for the non-timestamp bits, which provides statistical ordering within the same millisecond without additional state.

The practical result: if you insert 10,000 records per second into a PostgreSQL or MySQL table with a UUID v7 primary key, the B-tree index receives new entries in approximately sequential order. This eliminates the random page splits that plague UUID v4 indexes, reducing write amplification by 2–5x in typical workloads.

Database Indexing Benefits Over UUID v4

UUID v4 (random) generates uniformly distributed values that scatter inserts across every leaf page of a B-tree index. This causes frequent page splits, increases the working set size in the buffer pool, and degrades both write throughput and read locality. UUID v7 solves all three problems:

  • Sequential inserts: New UUIDs always land near the rightmost leaf page of the B-tree, similar to auto-increment integers. This keeps write I/O predictable and eliminates random page splits.
  • Hot page caching: Because recent inserts cluster together, the database buffer pool only needs to keep a small number of "hot" pages in memory, reducing cache misses by 60–80% compared to UUID v4 in benchmarks.
  • Range queries for free: Queries like "get all records created in the last hour" become simple range scans on the primary key β€” no additional timestamp index needed.
  • Reduced storage overhead: With sequential inserts, B-tree pages fill to ~90% capacity instead of the ~50% typical with random inserts, cutting index storage by nearly half.

For clustered indexes (InnoDB in MySQL, the default in CockroachDB), the improvement is even more pronounced because the entire row is stored in primary key order. Random UUIDs fragment the physical data layout; time-ordered UUIDs keep recent data physically contiguous on disk.

RFC 9562: The Modern UUID Standard

RFC 9562 (published May 2024) obsoletes the original RFC 4122 and formally defines UUID versions 1 through 8. UUID v7 is the RFC's recommended version for new implementations that need time-ordered, k-sortable identifiers. The specification explicitly states that v7 "is designed to be a time-based UUID that is suitable for use as a database key" (Section 5.7).

The bit layout for UUID v7 per RFC 9562:

  • Bits 0–47: Unix timestamp in milliseconds (big-endian)
  • Bits 48–51: Version field (fixed to 0111 = 7)
  • Bits 52–63: rand_a β€” 12 bits of random or monotonic counter data
  • Bits 64–65: Variant field (fixed to 10 = RFC 9562 variant)
  • Bits 66–127: rand_b β€” 62 bits of random data

This structure ensures that the timestamp occupies the most significant position in the 128-bit value, so standard string comparison (strcmp) and binary comparison produce chronological ordering. Libraries in every major language now support v7: Python's uuid7 package, Java 17+ with custom generators, Go's github.com/google/uuid v1.6+, and JavaScript's uuidv7 npm package.

When to Use UUID v7 vs UUID v4

Both versions are valid choices depending on your requirements:

  • Use UUID v7 when the identifier will be stored as a primary key in a database, when you need time-based ordering without an additional column, when insert performance matters at scale, or when you need to extract approximate creation time from the ID itself.
  • Use UUID v4 when you need maximum randomness with zero information leakage, when ordering is irrelevant (session tokens, CSRF tokens, temporary file names), or when you want zero external dependencies (built into every platform via crypto.randomUUID()).

Note that UUID v7 does leak creation time β€” anyone who reads the UUID can extract the millisecond timestamp. If this is a concern (for example, in user-facing URLs where creation time is sensitive), prefer UUID v4. For internal database keys where this information is already available via a created_at column, v7 adds no new exposure.

Code Examples

Generating UUID v7 in JavaScript and extracting the timestamp

// Using the uuidv7 npm package
import { uuidv7 } from 'uuidv7';

const id = uuidv7();
// β†’ "018f3c4a-1b2d-7000-9f3a-7c5e2b4d8a1f"

// Extract the embedded timestamp from a UUID v7
function extractTimestamp(uuid) {
  const hex = uuid.replace(/-/g, '').slice(0, 12);
  const ms = parseInt(hex, 16);
  return new Date(ms);
}

console.log(extractTimestamp(id));
// β†’ 2024-05-15T10:23:45.123Z (approximate creation time)

Using UUID v7 as PostgreSQL primary key

-- PostgreSQL 17+ supports gen_random_uuid() for v4;
-- For v7, use the pg_uuidv7 extension or application-generated values
CREATE EXTENSION IF NOT EXISTS pg_uuidv7;

CREATE TABLE orders (
  id UUID PRIMARY KEY DEFAULT uuid_generate_v7(),
  customer_id UUID NOT NULL,
  total DECIMAL(10, 2) NOT NULL,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Range query using the time-ordered UUID directly
-- No additional index on created_at needed!
SELECT * FROM orders
WHERE id >= uuid_generate_v7_from_timestamp('2024-05-01'::timestamptz)
  AND id <  uuid_generate_v7_from_timestamp('2024-06-01'::timestamptz);

Standards & Specifications