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

You are reviewing a pull request. Someone generated an identifier with Guid.NewGuid(), uuid.uuid4(), or crypto.randomUUID(). Nobody questions it. It compiles, it works, and collision risk is negligible.
This is the muscle memory of nearly every development team on the planet. GUID / UUID v4 has been the unquestioned default since RFC 4122 was published in July 2005. It is simple, widely supported, and effectively bulletproof in terms of uniqueness. So why would anyone change?
Because databases have evolved. Distributed systems have evolved. And in May 2024, the standards caught up: RFC 9562 introduced GUID / UUID v7 as the recommended time-ordered version, and major language runtimes have already shipped native support.
If you are a developer, this matters. Not because v4 is broken, but because v7 solves real problems that v4 was never designed to address.
What Actually Changed: v4 vs v7 in Plain English
Both GUID / UUID v4 and v7 are 128-bit identifiers using the standard 8-4-4-4-12 hex format. Both are non-deterministic. Both produce values that look like this:
v4 example: 5c98eda8-b852-4eec-9960-ac2e29d734f4
v7 example: 018f3f5e-1c2d-7a9b-8f10-3c4d5e6f7a8b
The difference is in how those 128 bits are allocated:
-
v4 fills 122 of its 128 bits with cryptographically random data. There is no order, no embedded metadata, and maximum privacy. The only non-random bits are the version nibble (
4) and the variant marker. -
v7 dedicates the first 48 bits to a Unix Epoch timestamp in milliseconds, followed by 74 bits of randomness. This means v7 IDs generated later are always lexicographically greater. They sort naturally by creation time.
The version nibble (4 vs 7) is the only visible difference in the string itself. Everything else — the format, the storage, the column types — stays the same.
For collision resistance, both versions are safe in any real-world scenario. V4 offers 122 random bits per ID (~5.3 × 10³⁶ possible values). V7 offers 74 random bits per millisecond (~1.9 × 10²² unique values per millisecond), combined with timestamp-based separation across milliseconds. You will not hit a collision with either version.
The Database Performance Story: Why This Matters at Scale
This is where the shift from v4 to v7 goes from “interesting” to “impactful.”
Most relational databases store primary keys in B-tree indexes. When you insert a row with a random v4 GUID / UUID as the key, that insert lands at a random position in the index. Over millions of rows, this causes:
- Page splits — the database has to reorganize index pages to make room for randomly placed values.
- Write amplification — more disk I/O per insert than necessary.
- Lower cache hit rates — recently accessed pages are unlikely to be reused because inserts are scattered.
- Index bloat — fragmented pages waste space over time.
V7 changes this fundamentally. Because the leading 48 bits are a timestamp, new inserts always cluster near the end of the index. The behavior becomes sequential-ish, similar to auto-increment integers. The result is dramatically fewer page splits, better write throughput, and reduced storage overhead.
This is not theoretical. In PostgreSQL, MySQL, SQL Server and most other relational databases, the difference is measurable at scale. Many teams that migrated from v4 to v7 primary keys report write performance approaching auto-increment integers — without losing the benefits of decentralized, coordination-free ID generation.
As a bonus, you get approximate chronological ordering for free. Sorting by the primary key yields a roughly chronological list, which simplifies pagination, event streaming, audit logs, and “latest first” queries. In many cases, this eliminates the need for a separate indexed created_at column entirely.
For a deeper dive into database-level behavior, see the GUID Database Performance and Indexing guide on GUIDsGenerator.com.
The Ecosystem Is Moving: Language and Framework Support
This is not a proposal or a draft spec. RFC 9562 was published in May 2024, and the major ecosystems have already shipped v7 support. Here is what the v4-to-v7 switch looks like in practice:
.NET (C#)
// v4 — available since .NET 1.0
var v4 = Guid.NewGuid();
// v7 — available since .NET 9
var v7 = Guid.CreateVersion7();
Python
import uuid
# v4 — available since Python 2.5
v4 = uuid.uuid4()
# v7 — available since Python 3.13
v7 = uuid.uuid7()
JavaScript / Node.js
// v4 — built-in (Web Crypto API / Node.js 19+)
const v4 = crypto.randomUUID();
// v7 — requires the 'uuid' package v9+
import { v7 as uuidv7 } from 'uuid';
const v7 = uuidv7();
Go
import "github.com/google/uuid"
// v4 — available since google/uuid v1.0
v4 := uuid.New()
// v7 — available since google/uuid v1.4
v7, _ := uuid.NewV7()
Rust
use uuid::Uuid;
// v4 — requires feature "v4"
let v4 = Uuid::new_v4();
// v7 — requires feature "v7", available since uuid crate v1.3
let v7 = Uuid::now_v7();
Java
import java.util.UUID;
// v4 — available since Java 1.5
UUID v4 = UUID.randomUUID();
// v7 — no built-in support yet
// Use a library like com.fasterxml.uuid (java-uuid-generator 5.0+)
// or com.github.f4b6a3:uuid-creator
The pattern is the same everywhere: a one-line function swap. Same column type. Same format. No schema migration. No infrastructure changes. No coordination between services.
V4 and v7 can coexist in the same system. Both are valid 128-bit GUIDs / UUIDs in the same canonical format, so you can migrate incrementally.
When v4 Is Still the Right Call
A good technical decision is never “always use the new thing.” V4 remains the better choice in several real scenarios:
Privacy-sensitive public identifiers. V7 embeds an approximate creation timestamp in the first 48 bits. Anyone with access to the GUID / UUID can extract when it was created. For URLs, API keys, session tokens or any identifier visible to end users where timing metadata must stay private, v4 is the safer choice.
Existing v4 ecosystems with no ordering needs. If your system already uses v4 everywhere and time-based sorting adds no value to your queries, switching introduces churn without meaningful gain. Do not fix what is not broken.
Maximum randomness per ID. V4 gives 122 random bits per identifier. V7 gives 74 random bits per millisecond. For extreme collision paranoia within a single time-tick, v4 offers a wider spread. But in reality this is not a meaningful concern — even v7’s 74 random bits per millisecond yield over 18 quintillion unique values per time-tick, which is far beyond what any system will ever generate.
Environments without reliable clocks. V7 depends on a reasonably accurate system clock. Embedded systems, sandboxed environments, or virtualized setups with significant clock drift may produce out-of-order IDs, undermining the entire point of time-ordering.
The bottom line: v4 is not deprecated, not going away, and remains perfectly valid. The choice should be driven by your actual constraints, not hype.
A Practical Decision Framework for Your Team
Here is a straightforward decision tree you can apply in code reviews, architecture discussions, and new project kickoffs:
| Scenario | Recommendation |
|---|---|
| New project, database primary keys | v7 — performance and sorting benefits are significant, migration cost is zero on greenfield |
| New project, public-facing tokens or API keys | v4 — timestamp disclosure is an unnecessary risk for externally visible identifiers |
| Existing v4 system, hitting index performance issues | Evaluate v7 — migrate hot tables first, v4 and v7 coexist safely |
| Existing v4 system, no performance complaints | Stay with v4 — revisit when starting new services or modules |
| Event streaming, audit logs, correlation IDs | v7 — natural chronological ordering simplifies debugging and querying |
| Internal microservice identifiers (no external exposure) | v7 — ordering and performance benefits outweigh minimal timestamp disclosure |
This is not about always choosing v7. It is about making GUID / UUID version selection a conscious decision rather than defaulting to whatever autocomplete suggests.
The Migration Is Simpler Than You Think
The most common objection is that migration sounds painful. In practice, it is a one-line change per call site:
| 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 needed. Both versions are 128-bit values stored in the same column types (uniqueidentifier in SQL Server, uuid in PostgreSQL, BINARY(16) in MySQL).
No coordination or central authority is required. V7 uses the same decentralized generation model as v4 — any node can generate IDs independently.
Existing v4 IDs in your database remain valid. New v7 rows will sort after them in most cases, since v7 timestamps are lexicographically greater than most random v4 values.
The practical migration path:
- Start by adopting v7 for new tables and new services.
- For existing high-write tables where you are seeing index fragmentation, evaluate whether migrating the ID generation call improves performance.
- Leave stable v4 systems alone unless there is a clear benefit to switching.
Make It a Conscious Choice
The industry is shifting toward v7 as the new default. This is not a trend piece — it is an RFC-backed standard with measurable performance implications and native runtime support across every major language.
As a tech lead, the right move is not to mandate v7 everywhere. It is to make GUID / UUID version selection a deliberate architectural decision instead of an afterthought.
Add it to your team’s design review checklist: “Which GUID / UUID version, and why?”
For most new work — especially anything touching databases, event streams, or distributed systems — v7 is the stronger default. For privacy-sensitive contexts, v4 remains the right tool. And for existing systems running fine on v4, there is no urgency to change.
The best identifier is not the newest one. It is the one chosen deliberately.
For a full side-by-side breakdown of every GUID / UUID version, see the GUID v4 vs v7 comparison and the complete version comparison on GUIDsGenerator.com.
If you want the easiest, fastest and rfc-compliant browser-based guid generator to quickly create unique identifiers, visit GUIDsGenerator.com.
Thank you for reading.
-Bruno