All Blogs
Backend Development

UUIDv4 vs UUIDv7: The Complete Guide to Modern Unique Identifiers

February 24, 2026
9 min read

If you've worked with databases, distributed systems, or modern web applications, you've almost certainly encountered UUIDs (Universally Unique Identifiers). They're the go-to solution for generating unique identifiers without a central authority critical for microservices, distributed databases, and scalable architectures.

But not all UUIDs are created equal. The two most prevalent formats you'll encounter today are UUIDv4 (random) and UUIDv7 (time-ordered). Understanding the fundamental differences between these two versions isn't just academic it can dramatically impact your application's performance, database efficiency, and ability to debug issues in production.

What Exactly is a UUID?

Before diving into the differences, let's establish what we're working with. A UUID is a 128-bit identifier formatted as a 36-character string (36 characters including hyphens), typically looking like this:

550e8400-e29b-41d4-a716-446655440000

The format follows the 8-4-4-4-12 pattern, which corresponds to the byte layout: 8 bytes + 4 bytes + 4 bytes + 4 bytes + 12 bytes = 16 bytes (128 bits).

UUIDs were standardized by the Open Software Foundation in 1989 and have evolved through several versions, each designed for different use cases.


UUIDv4: The Random Standard

UUIDv4 is the most commonly used UUID version. It generates identifiers using pseudo-random data for all non-version bits. Out of the 128 bits, 6 bits are reserved for the version (v4 = 0100) and variant bits, leaving 122 bits of pure randomness.

How UUIDv4 Works

A UUIDv4 looks like this:

6ba7b810-9dad-4d11-8019-c9ea1385e142

The key characteristic is that every single bit that isn't reserved for version/variant is randomly generated. This means:

  • No timestamp component: There's no embedded time information
  • Maximum entropy: 122 bits of randomness provides virtually zero collision probability
  • Truly random: No pattern, no order, no predictability

When UUIDv4 Shines

UUIDv4 is ideal for:

  1. Security-sensitive identifiers: The randomness makes UUIDv4s unpredictable, which is valuable for session tokens, API keys, and other security-related identifiers where predictability is a vulnerability.

  2. Distributed systems without time sync: Since UUIDv4 doesn't rely on timestamps, you don't need synchronized clocks across your distributed infrastructure.

  3. Privacy-focused applications: The lack of embedded information means UUIDv4 can't leak metadata about when or where something was created.


UUIDv7: The Time-Ordered Revolution

UUIDv7 was introduced in RFC draft (and now widely adopted) specifically to address the performance limitations of UUIDv4 in database contexts. It embeds a Unix timestamp in the most significant bits, making the identifiers time-sortable.

How UUIDv7 Works

A UUIDv7 looks like this:

018677af-6c9c-7b20-a3c0-9e4f5a1b2c3d

The structure is clever:

  • 48 bits for timestamp: Unix timestamp in milliseconds (can represent dates until year 10889)
  • 12 bits for randomness: A counter to handle millisecond-level collisions
  • Version and variant bits: Reserved as per UUID spec

The magic is in the most significant bits: because the timestamp comes first, UUIDv7s generated later will always have a higher lexical value than those generated earlier.

The Game-Changing Benefits

UUIDv7 provides several transformative advantages:

  1. Time-sortability: UUIDs can be sorted chronologically without storing additional timestamp fields
  2. Database optimization: When used as primary keys, time-ordered UUIDs provide excellent insertion patterns (B-tree friendly)
  3. Natural lexicographic ordering: Sequential inserts hit the right side of the B-tree, minimizing page splits and index fragmentation
  4. Built-in timestamp: You can extract the creation time directly from the UUID itself

The Performance Reality: Why UUIDv7 Changes Everything

This is where things get interesting for backend developers and database architects. The choice between UUIDv4 and UUIDv7 can have massive implications for database performance.

The B-Tree Problem with UUIDv4

Most databases use B-trees (or B+-trees) for primary key indexes. These structures are optimized for sequential inserts. Here's the problem with UUIDv4:

  1. Random inserts everywhere: Each new UUIDv4 is essentially random across the entire 128-bit space
  2. Constant page splits: Every insert potentially splits index pages, causing fragmentation
  3. Performance degradation: As the table grows, random inserts become increasingly expensive
  4. Cache inefficiency: The random distribution means more disk seeks

Think of it like trying to organize a library where each new book is placed in a randomly chosen shelf the librarian would be running around constantly!

How UUIDv7 Solves This

UUIDv7's time-ordered nature means:

  1. Append-only inserts: New rows go to the "end" of the index
  2. Sequential I/O: Better disk write patterns, especially for spinning disks
  3. Reduced fragmentation: Minimal page splits, compact indexes
  4. Better cache locality: Recent data clusters together

Benchmarks Don't Lie

In practical benchmarks comparing UUIDv4 vs UUIDv7 as primary keys:

  • Insert throughput: UUIDv7 often shows 2-10x better insert performance
  • Index size: UUIDv7 indexes are typically smaller due to less fragmentation
  • Query performance: Range queries on time-ordered keys are significantly faster
  • Disk I/O: Sequential writes reduce I/O wait times substantially

Semantic Meaning: What Can You Extract?

Another critical difference is the information density of each UUID type:

UUIDv4: The Black Box

6ba7b810-9dad-4d11-8019-c9ea1385e142

From a UUIDv4, you can extract:

  • Nothing useful: It's pure randomness
  • Version: It's version 4
  • Variant: It's the standard variant

That's it. You need external systems to know when or where it was created.

UUIDv7: The Information Container

018677af-6c9c-7b20-a3c0-9e4f5a1b2c3d

From a UUIDv7, you can extract:

  • Timestamp: The exact creation time (down to millisecond precision)
  • Version: It's version 7
  • Variant: It's the standard variant

This embedded timestamp becomes incredibly valuable for:

  • Auditing and compliance
  • Debugging production issues
  • Analyzing user behavior patterns
  • Data retention policies

A Practical Decision Framework

Here's a practical guide to help you choose:

Choose UUIDv4 When:

  • Security tokens: API keys, session IDs, password reset tokens (unpredictability matters)
  • Distributed generation: Systems that can't synchronize clocks but need unique IDs
  • Privacy requirements: When you don't want to leak creation timestamps
  • Public identifiers: When the ID will be exposed externally and predictability isn't a concern

Choose UUIDv7 When:

  • Database primary keys: The default choice for modern applications using PostgreSQL, MySQL, or other relational databases
  • Audit trails: When you need to know when records were created
  • Log correlation: When tracing events across distributed systems
  • Time-based queries: When you'll frequently query by "created around this time"
  • Ordered data: When insertion order matters for performance

Migration Strategies: Moving from v4 to v7

If you're currently using UUIDv4 and want to migrate to UUIDv7, here's what to consider:

Option 1: Dual-Write Period

  1. Generate both UUIDv4 and UUIDv7 for new records
  2. Migrate historical data in batches
  3. Switch reads to UUIDv7 once migration is complete
  4. Drop UUIDv4 column after full migration

Option 2: UUIDv7 as Secondary Index

  1. Add a new UUIDv7 column alongside your existing UUIDv4 primary key
  2. Populate UUIDv7 for new records
  3. Backfill UUIDv7 for existing records
  4. Switch primary key to UUIDv7 once comfortable

Important Considerations

  • Existing data: UUIDv7s for existing records will have the current timestamp, not the original creation time (unless you preserve it)
  • Client changes: Ensure all clients can handle the new format
  • External integrations: Check if any external systems depend on the UUID format
  • Backup and restore: Test your migration process thoroughly

Implementation in Popular Languages

JavaScript/TypeScript

// UUIDv4
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4();

// UUIDv7 (using a library like 'uuid' v9+)
import { v7 as uuidv7 } from 'uuid';
const id = uuidv7();

Python

import uuid

# UUIDv4
id = uuid.uuid4()

# UUIDv7 (requires 'uuid' >= 1.6 or external library)
import uuid7
id = uuid7.uuid7()

Go

import (
    "github.com/google/uuid"
)

// UUIDv4
id := uuid.Must(uuid.NewRandom())

// UUIDv7 (requires 'github.com/google/uuid' >= 1.3)
id := uuid.Must(uuid.NewUUID())

The Future: UUIDv8 and Beyond

The UUID specification continues to evolve. UUIDv8 was recently standardized in RFC 9562 (May 2024), offering:

  • Custom timestamp: Allows embedding custom time sources
  • Greater flexibility: Can accommodate different epoch starting points
  • Future-proof: Designed for specialized use cases

However, UUIDv7 remains the recommended default for most applications due to its balance of standardization, performance, and semantic value.


Summary: Key Takeaways

AspectUUIDv4UUIDv7
Structure122 bits of randomness48-bit timestamp + 74 bits random
OrderingRandom, unsortableTime-sortable
Collision RiskVirtually zeroExtremely low (12-bit counter)
Insert PerformancePoor (random B-tree inserts)Excellent (sequential inserts)
MetadataNone (black box)Creation timestamp embedded
Best ForSecurity tokens, privacyPrimary keys, audit trails

Conclusion

The choice between UUIDv4 and UUIDv7 isn't just academic it has real implications for your application's performance, maintainability, and scalability. For most modern applications, especially those using relational databases, UUIDv7 should be your default choice for primary keys and internal identifiers. Its time-ordered nature provides significant performance benefits while embedding valuable timestamp metadata.

However, UUIDv4 remains invaluable for security-sensitive applications where unpredictability is a feature, not a bug. Understanding both and knowing when to use each is a mark of a well-rounded backend developer.

As always, the best choice depends on your specific use case. But now you're equipped to make that decision informed by a deep understanding of how these identifiers work under the hood.