Scanning database...
Tools
Articles

No matches found for ""

View All Results
Home / Compare ID Formats
Protocol Benchmarks — Updated 2024

UUID vs ULID vs NanoID vs GUID

A complete technical comparison of every major identifier format. Sortability, entropy, database performance, storage cost, and the right choice for your architecture.

6
ID Formats Compared
128-bit
Standard Size
RFC 9562
Latest Standard
v7
Best for Databases
Comparison Matrix

Full Feature Comparison

Format Standard Bits Length Sortable URL Safe DB Perf Privacy Best For
UUID v4 RFC 4122 128 36 ★★☆ ★★★ General purpose, user IDs, tokens
UUID v7 RFC 9562 128 36 ★★★ ★★★ Database PKs, event sourcing
UUID v1 RFC 4122 128 36 ~ ★★☆ ★☆☆ Legacy systems, Cassandra
UUID v6 RFC 9562 128 36 ★★★ ★★★ v1 migration, sortable IDs
ULID ULID Spec 128 26 ★★★ ★★★ APIs, URLs, event logs
NanoID Custom Var 21 ★★☆ ★★★ Short URLs, tokens, slugs
GUID Microsoft 128 36 ★★☆ ★★★ .NET, SQL Server, Windows

★★★ Excellent  ·  ★★☆ Good  ·  ★☆☆ Limited

Database Performance

INSERT Throughput at Scale

Relative INSERT performance on a B-tree indexed primary key column with 100M rows (PostgreSQL benchmark). Higher is better.

Relative INSERT Throughput

UUID v7 97%
UUID v6 95%
ULID 94%
GUID (seq) 78%
UUID v1 55%
NanoID 48%
UUID v4 38%
GUID (rand) 36%

Normalized to UUID v7 = 100%. Based on PostgreSQL 16 benchmarks.

Index Bloat After 100M Inserts

UUID v4 High fragmentation
GUID (rand) High fragmentation
NanoID High fragmentation
UUID v1 Moderate
GUID (seq) Low
ULID Minimal
UUID v6 Minimal
UUID v7 Minimal

Lower is better. Fragmentation causes slower reads and higher storage cost.

Format VARCHAR storage Binary storage Savings vs VARCHAR Native DB type
UUID v4/v7/v6/v1 36 bytes 16 bytes 56% PostgreSQL UUID, MySQL BINARY(16), SQL Server UNIQUEIDENTIFIER
GUID 38 bytes 16 bytes 58% SQL Server UNIQUEIDENTIFIER
ULID 26 bytes 16 bytes 38% VARCHAR(26) or BINARY(16)
NanoID (21) 21 bytes N/A VARCHAR(21)
Security Analysis

Entropy & Collision Resistance

Random bits determine how hard it is to guess or collide an identifier. More bits = more security.

Random Bits per Identifier

UUID v4
122 bits
NanoID 21
126 bits
ULID
80 bits
UUID v7
74 bits
UUID v6
62 bits
UUID v1
62 bits
GUID
122 bits
Best for Security
NanoID (21 chars)

126 bits of entropy. Slightly more than UUID v4. URL-safe and compact.

Best Balance
UUID v4 / GUID

122 bits. Industry standard. Native support in every database and language.

Time-ordered Trade-off
UUID v7 / ULID

74–80 random bits. Timestamp is predictable by design — not a weakness for most use cases.

Privacy Concern
UUID v1 (standard)

Exposes MAC address in node field. Use random node ID (our generator does this by default).

Collision Calculator

Birthday Paradox Probability

Using the birthday paradox approximation: P ≈ n² / (2N) where n = IDs generated and N = total possible values.

1K1B1T
Random Bits
Collision Probability

Probability of at least one collision among generated IDs using .

Context
At 1 billion IDs/day, UUID v4 takes ~85 years to reach 50% collision probability.
UUID v7 has fewer random bits but the timestamp prefix makes real-world collisions even less likely.
For most applications generating under 1 trillion IDs total, any format here is safe.
Decision Wizard

Which Format Should You Use?

Answer 3 questions and get a tailored recommendation for your use case.

Do you need identifiers to be sortable by creation time?

What is your primary environment?

Any specific constraints?

Open Generator
Deep Dive

The Complete Guide to Choosing an Identifier Format

Choosing the wrong identifier format is one of the most common and costly architectural mistakes in software development. A decision made early — often without much thought — can haunt a system for years in the form of slow queries, index fragmentation, security vulnerabilities, or painful migrations. This guide covers every major format in depth so you can make the right choice the first time.

Why Identifier Format Matters More Than You Think

In a small application with a few thousand records, the choice between UUID v4 and UUID v7 is irrelevant. But as systems scale to millions or billions of records, the identifier format becomes a critical performance variable. The primary key of a database table is indexed — and the structure of that index determines how efficiently the database can insert, update, and query records.

B-tree indexes — used by PostgreSQL, MySQL InnoDB, SQL Server, and SQLite — are optimized for sequential inserts. When new records always have a larger key than existing records, they are appended to the rightmost leaf page of the tree. Pages fill sequentially, splits are rare, and the index stays compact. This is how auto-incrementing integers work, and it is why they have historically been the default choice for primary keys.

UUID v4 breaks this pattern completely. Because v4 is fully random, each new record is inserted at a random position in the B-tree. When a page is full and a new record needs to be inserted in the middle, the database must split the page — copying half the records to a new page and updating parent pointers. At scale, this causes significant write amplification, index fragmentation, and degraded performance. UUID v7 and ULID solve this problem by embedding a timestamp prefix, restoring the sequential insert behavior while maintaining global uniqueness.

UUID v4: The Universal Default

UUID v4 is the most widely deployed identifier format in the world. Its 122 bits of cryptographic randomness make it effectively impossible to guess or collide. It is supported natively in every major programming language, database, and cloud platform. For most applications — especially those with fewer than 10 million records — UUID v4 is a perfectly reasonable choice.

The security properties of UUID v4 are particularly valuable for public-facing identifiers. Unlike sequential integers, a UUID v4 cannot be enumerated. A user who knows their own ID (550e8400-e29b-41d4-a716-446655440000) cannot derive another user's ID by incrementing a number. This prevents Insecure Direct Object Reference (IDOR) attacks at the identifier level.

The main limitation of UUID v4 is database performance at scale. For tables with more than 50 million rows where INSERT throughput is critical, the random insertion pattern causes measurable degradation. In these cases, UUID v7 is the recommended upgrade path.

UUID v7: The Modern Standard for Databases

UUID v7, ratified in RFC 9562 in May 2024, is the most significant advancement in identifier standards in nearly two decades. It combines a 48-bit Unix millisecond timestamp with 74 bits of randomness, producing an identifier that is both globally unique and lexicographically sortable by creation time.

The performance implications are substantial. In benchmarks on PostgreSQL with 100 million rows, UUID v7 achieves 2–5x better INSERT throughput compared to UUID v4, with 80–90% less index bloat. The reason is simple: because the timestamp prefix increases monotonically, new records are always appended to the end of the B-tree index. Pages fill sequentially, splits are rare, and the index remains compact and cache-friendly.

UUID v7 also makes it trivial to extract the creation time from an identifier — the first 12 hex characters encode the Unix timestamp in milliseconds. This eliminates the need for a separate created_at column for basic time queries, reducing schema complexity. For any new system using a relational database, UUID v7 should be the default choice for primary keys.

ULID: The URL-Friendly Alternative

ULID (Universally Unique Lexicographically Sortable Identifier) offers the same time-ordering benefits as UUID v7 but in a more compact, URL-friendly format. At 26 characters using Crockford Base32 encoding, ULID is 28% shorter than a UUID string and contains no hyphens — making it safe to use directly in URLs without percent-encoding.

ULID's 80 random bits (vs. UUID v7's 74) provide slightly more entropy per millisecond, though both are more than sufficient for any real-world application. The Crockford Base32 alphabet excludes visually ambiguous characters (I, L, O, U), making ULIDs easier to read, type, and speak aloud — a useful property for invite codes, support tickets, and other human-facing identifiers.

The main limitation of ULID is the lack of native database type support. While UUID has native types in PostgreSQL, MySQL, and SQL Server, ULID is typically stored as VARCHAR(26) or BINARY(16). For applications where URL ergonomics matter more than database native support, ULID is an excellent choice.

NanoID: Compact and Customizable

NanoID is the most flexible identifier format in this comparison. Its customizable alphabet and length make it adaptable to a wide range of use cases — from 6-digit numeric OTP codes to 32-character high-entropy tokens. The default configuration (21 characters, 64-character alphabet) provides ~126 bits of entropy, slightly more than UUID v4.

NanoID is particularly well-suited for short URL slugs, invite codes, and API tokens where compactness and URL safety are priorities. Its rejection-sampling algorithm ensures uniform distribution across the alphabet, avoiding the modulo bias that affects many naive ID generators.

Like UUID v4, NanoID is not time-ordered. For database primary keys at scale, UUID v7 or ULID are better choices. NanoID shines in application-layer identifiers where the ID will appear in URLs, be displayed to users, or be typed manually.

GUID: The Windows Ecosystem Standard

GUID is Microsoft's name for UUID. Structurally identical to UUID v4, GUIDs are the standard identifier format across the entire Microsoft ecosystem — .NET, SQL Server, Azure, Windows Registry, COM, and MSI installers. If you are building on the Microsoft stack, GUID is the natural choice.

SQL Server's NEWID() generates random GUIDs (equivalent to UUID v4), while NEWSEQUENTIALID() generates sequential GUIDs that reduce index fragmentation. For new SQL Server applications, consider generating UUID v7 client-side and storing it as a UNIQUEIDENTIFIER — this gives you the sequential benefits without the server-restart reset issue of NEWSEQUENTIALID().

UUID v1 and v6: The Legacy Formats

UUID v1 was the original time-based UUID, combining a 60-bit Gregorian timestamp with a MAC address node ID. While it embeds creation time, the timestamp fields are scrambled across the UUID string in a non-sortable order. The MAC address exposure is a privacy concern in modern applications, though this can be mitigated by using a random node ID.

UUID v6 fixes v1's sortability problem by reordering the timestamp fields so that the most significant bits come first. It is fully backward-compatible with v1 and is the recommended migration path for systems already using v1. For new systems, UUID v7 is preferred over v6 due to its simpler Unix epoch timestamp and broader library support.

Apache Cassandra's timeuuid type is UUID v1. If you are working with Cassandra, v1 (or v6 for sortability) is the natural choice. For all other new systems, v7 is the modern standard.

Summary: The Right Format for Every Use Case

Database primary keys (new systems)
UUID v7 →
Database primary keys (SQL Server)
GUID + NEWSEQUENTIALID or UUID v7 →
REST API resource identifiers
ULID or UUID v4 →
User IDs, session tokens
UUID v4 →
Short URLs, invite codes, slugs
NanoID →
Windows / .NET / Azure applications
GUID →
Migrating from UUID v1
UUID v6 →
Apache Cassandra timeuuid
UUID v1 →
Event sourcing / audit logs
UUID v7 or ULID →
Engineering Journal

Latest from the Blog

All Articles