uuiddatabaseperformanceprimary-keys

UUID v4 vs UUID v7 — Which Should You Use for Database Primary Keys?

·7 min read

UUID v4 vs UUID v7 — The Full Picture

UUIDs are the standard identifier for modern distributed systems. But not all UUIDs are equal. The version matters a lot, especially at database scale.

UUID v4 — Completely Random

UUID v4 generates 122 random bits. It looks like:

f47ac10b-58cc-4372-a567-0e02b2c3d479
         ^^^^                          ← version 4

Version 4 is the most widely used. It is statistically unique — the probability of two v4 UUIDs colliding is roughly 1 in 5 × 10^36, which is effectively impossible in practice.

Generate UUID v4 in different languages:

javascript
// JavaScript / Node.js
crypto.randomUUID()  // Built-in since Node 14.17 and all browsers

// Output: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
python
# Python
import uuid
str(uuid.uuid4())
go
// Go — github.com/google/uuid
import "github.com/google/uuid"
id := uuid.New().String()

The Problem with UUID v4 in Databases

UUID v4 is completely random — consecutive inserts have completely unrelated ID values. This causes a serious performance problem with B-tree indexes:

  • Row 1 ID: f47ac10b-... → index position 15,032
  • Row 2 ID: 3b8e9d42-... → index position 4,891
  • Row 3 ID: c9a7f16e-... → index position 22,771

The database has to jump to a different part of the B-tree for every insert. This causes random page splits — each insert potentially reads a different disk page into memory, thrashes the buffer pool, and creates fragmented indexes.

At small scale this is invisible. At millions of rows per day, it degrades INSERT throughput by 30–60% and increases index size significantly.

UUID v7 — Time-Sortable

UUID v7 encodes a 48-bit millisecond timestamp in the first 12 hex characters, followed by random bits:

01924b3d-2a0f-7b42-a891-f47ac10b58cc
^^^^^^^^ ^^^^  ^                      ← timestamp + version 7

Because the timestamp prefix is always increasing, consecutive v7 UUIDs sort naturally by creation time. The database always appends to the end of the B-tree — the same efficient sequential pattern as autoincrement integers.

Generate UUID v7:

javascript
// No built-in support yet — use the uuid package
import { v7 as uuidv7 } from 'uuid';
uuidv7()  // "01924b3d-2a0f-7b42-a891-f47ac10b58cc"
python
# Python 3.12+
import uuid
str(uuid.uuid7())
go
// Go — github.com/google/uuid (since v1.6.0)
import "github.com/google/uuid"
id := uuid.Must(uuid.NewV7()).String()

Performance Comparison

MetricUUID v4UUID v7
Index fragmentationHighLow
INSERT performanceDegrades at scaleNear-sequential
Storage overheadSameSame
Sortable by timeNoYes
Collision resistanceExtremely highEven higher

At 1 million inserts/day, the difference is negligible. At 10 million inserts/day, v7 is measurably faster and produces significantly smaller, less fragmented indexes.

When to Use Each

Use UUID v4 when: - You need maximum compatibility (v4 is supported everywhere) - The volume is small (under a few million rows) - You do not need time-based sorting - You are using a system that does not yet support v7

Use UUID v7 when: - Using UUIDs as database primary keys (PostgreSQL, MySQL, MongoDB) - Inserting at high volume - You need records sortable by creation time - Building new systems where you control the ID generation

Database Recommendations

PostgreSQL: UUID v7 + pgcrypto or the uuid-ossp extension. Store as UUID type.

MySQL 8+: UUID v7 stored as BINARY(16) for best performance (avoid VARCHAR(36)).

MongoDB: ObjectId is MongoDB's native time-sortable ID. For external compatibility, UUID v7 as a string works well.

Check Your UUIDs Online

Use JSONKit's UUID Generator to generate UUID v4 and v7 in bulk. The tool uses crypto.randomUUID() for maximum entropy and lets you copy 1–100 UUIDs at once.

Try UUID Generator

Generate UUID v4 and v7 in bulk — cryptographically random or time-sortable. Free, instant.