UUID v4 vs v7: What Changed and Why It Matters

Published: (February 5, 2026 at 09:12 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

📌 UUID v4 – Pure Randomness

f47ac10b-58cc-4372-a567-0d8b62691e10
         ^^^^
         version 4

How it works

  1. Generate 128 random bits.
  2. Set the version (4 bits → 0100).
  3. Set the variant (2 bits → 10).
  4. Format as an 8‑4‑4‑4‑12 hex string.

The good

  • Dead simple to generate.
  • Statistically unique (2¹²² 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.
  • Cannot extract any useful metadata.
  • Causes 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, Database‑Friendly

019526de-a3c0-7cc0-b2e8-4a1b3c5d7e9f
^^^^^^^^ ^^^^
timestamp  version 7

How it works

  1. Take the current Unix timestamp in milliseconds (48 bits).
  2. Set the version (4 bits → 0111).
  3. Set the variant (2 bits → 10).
  4. Fill the remaining 62 bits with random data.
  5. Format as a standard UUID string.

Structure

BitsMeaning
48Timestamp (ms)
4Version (7)
12Random a
2Variant (10)
62Random 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 size, same string format.

The trade‑offs

  • Leaks creation time (first 48 bits are the timestamp).
  • Slightly less randomness than v4 (62 vs 122 random bits).
  • Newer – not all libraries support it yet.

📈 Why Ordering Matters for Primary Keys

When you use UUID v4 as a primary key in a B‑tree indexed table (the default for most tables), every INSERT goes to a random location in the index, causing:

  • Page splits – constant B‑tree re‑organization.
  • Cache misses – no locality of reference.
  • Write amplification – more I/O per insert.
  • Index bloat – fragmented pages with wasted space.

At scale, this hurts performance.

UUID v7 fixes that

Because UUID v7 values are time‑ordered, new inserts always go to the end of the B‑tree:

  • 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‑10× better INSERT performance with UUID v7 vs v4 on PostgreSQL and MySQL, depending on table size and workload.


✅ When to Use Which Version

ScenarioRecommendation
Database primary keyv7
API request tracingv7
Session tokensv4
Event sourcingv7
Password‑reset tokensv4
Distributed log entriesv7
Cache keys (no ordering needed)v4

Decision matrix (quick glance)

NeedUse v4Use v7
Zero information leakage (timestamps are sensitive)
Maximum entropy for secrets/tokens
No ordering required (in‑memory lookups, hash maps)
Only v4 supported by the system
IDs are DB primary keys (main use case)
Want natural chronological ordering
Need to extract creation time from the ID
Distributed systems needing time‑ordered events
Care about DB performance at scale

🛠️ How to Generate UUID v7

Node.js (v20+)

import { randomUUID } from 'crypto';

// v4 only (as of Node 22)
const idV4 = randomUUID();

For v7, use a library:

import { v7 as uuidv7 } from 'uuid';
const idV7 = 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();

Online

createuuid.com – generates v1, v4, and v7 instantly in your browser, with bulk‑generation support.


🕵️ Extracting the Timestamp from a UUID v7

function extractTimestamp(uuidV7) {
  const hex = uuidV7.replace(/-/g, '');
  const timestampHex = hex.substring(0, 12); // first 48 bits = 12 hex chars
  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.


🤔 Should I Migrate 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:

  1. Use v7 for new tables and services.
  2. Keep v4 where it already exists.
  3. Let the natural lifecycle of your system handle the transition.

Exception: If you’re experiencing real performance issues from UUID v4 index fragmentation at scale—and you’ve confirmed UUIDs are the bottleneck—a planned migration may be justified.


📊 Quick Comparison

FeatureUUID v4UUID v7
IntroducedRFC 4122 (2005)RFC 9562 (2024)
Random bits12262
Time‑ordered?
DB performance at scalePoorExcellent
Timestamp readable?
Best forTokens, secretsPrimary keys, events

🎯 Bottom Line

  • 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.
  • For tokens, secrets, or any case where ordering isn’t needed, stick with v4.

Need UUIDs right now?

Try createuuid.com – free, instant, no signup.

This article is part of the Developer Tools Deep Dives series, where we explain the “why” behind the tools you use every day.

Back to Blog

Related posts

Read more »

Implementing gRPC.

gRPC is a framework developed by Google that provides an efficient, language‑independent mechanism for making Remote Procedure Calls RPCs. Its primary use case...

How can I learn Python (free)?

Hi! I’m new to the tech world and I want to learn Python to start my coding journey. I have already learned a little HTML, but I realized I don’t enjoy web deve...