DEV Community

Snappy Tools
Snappy Tools

Posted on • Originally published at snappytools.app

UUID v4 vs UUID v7: Which Should You Use in Your Database?

UUID v7 was ratified in May 2024 as part of RFC 9562. If you haven't heard about it yet, you're not alone — but you should have, because it solves a real performance problem with UUID v4 in databases.

Here's what changed and when you should switch.


The problem with UUID v4

UUID v4 is randomly generated. That's its feature — 122 bits of randomness, cryptographically secure, essentially no collision risk.

But "randomly generated" is also its flaw in databases.

When you insert a UUID v4 as a primary key, the index (typically a B-tree) has to put the new row somewhere in the middle of the tree — because the random value could land anywhere in the 0x0000...0000–0xFFFF...FFFF range. This causes:

  • Index fragmentation — rows are scattered across disk pages
  • Page splits — as the index fills, new insertions force expensive splits
  • Cache thrashing — frequently-accessed pages don't stay in memory; random UUIDs always land on different pages

For low-traffic apps, this doesn't matter. At scale — millions of rows, high write rates — this becomes measurable.


What UUID v7 does differently

UUID v7 is time-ordered. The first 48 bits are a Unix millisecond timestamp. The rest is random.

v7 format:
xxxxxxxx-xxxx-7xxx-xxxx-xxxxxxxxxxxx
^^^^^^^^ ^^^^^^^^^^ 48-bit millisecond timestamp at start
                         ^^^^^^^^^^^ random bits for uniqueness
Enter fullscreen mode Exit fullscreen mode

Because the timestamp prefix increases monotonically, new UUIDs always land at the end of the B-tree index — just like an auto-increment integer. This avoids fragmentation and page splits entirely.

Same uniqueness guarantees as v4. Much better database behaviour.


The timestamp means you get free metadata

Every v7 UUID encodes when it was created. You can extract the timestamp from the UUID itself:

function uuidV7Timestamp(uuid) {
  const hex = uuid.replace(/-/g, '').slice(0, 12); // first 48 bits
  const ms = parseInt(hex, 16);
  return new Date(ms).toISOString();
}

uuidV7Timestamp('018f4e1a-8b3c-7abc-8def-1234567890ab');
// → '2024-05-14T10:23:54.748Z'
Enter fullscreen mode Exit fullscreen mode

This is useful for debugging and auditing — you can tell at a glance when a record was created without querying the database.

UUID v1 also had a timestamp, but encoded it in a confusing non-monotonic format (time_low, time_mid, time_high). v7 just puts the milliseconds at the start, which is much cleaner.


When to use v4 vs v7

Use UUID v4 when:

  • The UUID is for something other than a database primary key (session tokens, nonces, API keys, file names)
  • You don't want the creation time to be recoverable from the ID
  • You're not concerned about write performance at scale

Use UUID v7 when:

  • It's a database primary key (especially in Postgres, MySQL, or any B-tree indexed store)
  • You're writing at high volume (tens of thousands of inserts/minute)
  • You want naturally sortable IDs without a separate created_at column

Avoid UUID v1 in new systems. It's time-ordered but the format is confusing, and it leaks the host's MAC address in the node bits (a historical security issue).


Database support

Database Notes
PostgreSQL No native UUID v7 type yet; store as uuid or varchar(36) — indexes sort correctly because v7 is lexicographically ordered
MySQL / MariaDB Same — char(36) works; for best performance, consider binary(16) with a custom function
MongoDB Uses its own ObjectId format (also time-ordered) — v7 UUID is fine but redundant
SQLite Any string column; v7 sorts correctly

PostgreSQL 17 has preliminary discussion around native UUID v7 functions, but nothing merged yet.


Generating UUID v7 in code

JavaScript (Node.js or browser):

// From the 'uuid' npm package (v10+)
import { v7 as uuidv7 } from 'uuid';
console.log(uuidv7()); // 018f4e1a-8b3c-7abc-8def-1234567890ab
Enter fullscreen mode Exit fullscreen mode

Python:

import uuid
# Built-in uuid.uuid7() available in Python 3.13+
# Otherwise use the 'uuid-utils' package
import uuid_utils
print(str(uuid_utils.uuid7()))
Enter fullscreen mode Exit fullscreen mode

Go:

// github.com/google/uuid
import "github.com/google/uuid"
id := uuid.New() // v4 by default
id7 := uuid.Must(uuid.NewV7()) // v7
Enter fullscreen mode Exit fullscreen mode

Try it in the browser

You can generate and inspect UUID v4 and v7 values without installing anything — the tool below runs entirely in your browser:

UUID Generator — snappytools.app

It also decodes any UUID: paste a v7 UUID and it will show you the embedded timestamp, version, and variant bits.


UUID v7 is a small change with a meaningful performance benefit for write-heavy databases. If you're starting a new project with UUID primary keys, there's no reason to use v4.


SnappyTools builds free, fast, browser-based tools for developers and designers. No signup, no data uploaded.

Top comments (0)