Skip to main content

Command Palette

Search for a command to run...

GUID v4 vs v7: Why You Should Care About the Shift

Updated
5 min read
B
https://brunovt.be/

You are reviewing a pull request and see Guid.NewGuid(), uuid.uuid4(), or crypto.randomUUID(). It works, it compiles, and no one usually questions it.

That has been the default for years. GUID / UUID v4 is simple, widely supported, and effectively unique in real-world systems. So why change?

Because databases have evolved, distributed systems have evolved, and the standards have finally caught up. In 2024, RFC 9562 introduced GUID / UUID v7 as the time-ordered option, and major runtimes are already adding support.

This matters because v4 is not broken, but v7 solves problems v4 was never built to handle.

What Actually Changed: v4 vs v7

Both GUID / UUID v4 and v7 are 128-bit identifiers using the familiar 8-4-4-4-12 format. They look similar, but they are built differently.

  • v4 is almost entirely random. It gives you maximum unpredictability and no built-in ordering.

  • v7 puts a Unix timestamp in the first 48 bits, then adds randomness. Newer IDs sort naturally by creation time.

The visible difference is just the version digit: 4 versus 7. The storage format stays the same, and both are safe from collisions in practical systems.

Why v7 Matters in Databases

This is where v7 becomes more than a spec update.

Most relational databases use B-tree indexes for primary keys. With a random v4 GUID, inserts land all over the index. Over time, that leads to more page splits, more disk I/O, lower cache efficiency, and index fragmentation.

V7 behaves much more like an auto-increment key. Because new values cluster at the end of the index, inserts become more sequential. That usually means fewer page splits, better write performance, and less index bloat.

It also gives you chronological ordering for free. Sorting by the identifier often gives you a rough creation order, which is useful for pagination, audit trails, and event streams.

Language Support Is Already Arriving

RFC 9562 is not theoretical. The ecosystem is moving quickly, and v7 support is already landing in popular runtimes.

.NET

var v4 = Guid.NewGuid();
var v7 = Guid.CreateVersion7();

Python

import uuid

v4 = uuid.uuid4()
v7 = uuid.uuid7()

JavaScript / Node.js

const v4 = crypto.randomUUID();

import { v7 as uuidv7 } from 'uuid';
const v7 = uuidv7();

Go

v4 := uuid.New()
v7, _ := uuid.NewV7()

Rust

let v4 = Uuid::new_v4();
let v7 = Uuid::now_v7();

Java

UUID v4 = UUID.randomUUID();
// v7 still requires a library

The pattern is the same almost everywhere: a small code change, no schema change, and no central coordination.

v4 and v7 can also coexist in the same system, which makes migration much easier.

When v4 Is Still the Better Choice

Choosing v7 does not mean v4 is obsolete. There are still cases where v4 makes more sense.

  • Public identifiers and tokens. V7 exposes an approximate creation time, which may be undesirable for URLs, API keys, or session tokens.

  • Existing systems with no ordering needs. If v4 is already working well and ordering adds no value, there may be no reason to change.

  • Maximum randomness per ID. V4 gives more random bits overall, even if that rarely matters in practice.

  • Unreliable clocks. V7 depends on a reasonably accurate system clock, so some environments may be a poor fit.

In short, v4 is not deprecated. It is just no longer the only serious option.

A Simple Decision Rule

Here is a practical way to choose:

Scenario Recommendation
New database primary keys v7
Public-facing API keys or tokens v4
Existing v4 system with performance issues Evaluate v7
Existing stable v4 system Stay with v4
Event logs, audit trails, correlation IDs v7

The goal is not to force v7 everywhere. The goal is to stop treating GUID version choice as an afterthought.

The Migration Is Simpler Than It Sounds

For most teams, migration is just a one-line swap at the point where IDs are generated.

Language v4 v7
.NET Guid.NewGuid() Guid.CreateVersion7()
Python uuid.uuid4() uuid.uuid7()
Node.js uuidv4() uuidv7()
Go uuid.New() uuid.NewV7()
Rust Uuid::new_v4() Uuid::now_v7()

No schema changes are required. Both versions fit the same column types, whether you use uuid, uniqueidentifier, or BINARY(16).

  1. Use v7 for new tables and services.

  2. Test it on high-write tables where index fragmentation matters.

  3. Leave stable v4 systems alone unless there is a real reason to switch.

Make the Choice Deliberate

The industry is moving toward v7 as the new default, and for many systems that makes sense. It is faster for indexed inserts, easier to sort, and supported by the latest standards.

Still, the right decision depends on context. v7 is a strong default for databases, logs, and distributed systems. v4 is still the better fit for privacy-sensitive identifiers and systems that do not benefit from ordering.

The key is to choose deliberately.

If you enjoyed this post, follow me for more content like this!

Thanks for reading.

Bruno