Try the Random String Generator

UUID v4 vs UUID v7 vs ULID vs NanoID: Which Identifier Format Should You Use?

UUID v4's random bits fragment database B-tree indexes, causing write amplification. UUID v7 adds a millisecond timestamp prefix to fix this. ULID is sortable and URL-safe without hyphens. NanoID is compact and customisable. Here's how each works and when to choose each format.

By sadiqbd Β· June 13, 2026

Share:
UUID v4 vs UUID v7 vs ULID vs NanoID: Which Identifier Format Should You Use?

UUID v4 is not always the right identifier β€” and v7, ULID, and NanoID each solve specific problems it doesn't

UUIDs (Universally Unique Identifiers) are the default choice for generating identifiers in most applications. UUID v4 β€” 122 random bits presented as a 36-character hyphenated string β€” is simple, unique, and widely supported. But it has a specific problem in databases: random UUIDs fragment B-tree indexes because new rows insert at random positions, causing page splits and poor cache locality.

Newer identifier formats solve this while maintaining collision resistance. Choosing the right format depends on whether you need sortability, compactness, or specific entropy characteristics.


UUID v4: the current default

A UUID v4 looks like: 550e8400-e29b-41d4-a716-446655440000

Structure: 128 bits total. 4 bits for the version (0100 = v4). 2 bits for variant. 122 bits of random data.

Collision probability: with 122 bits of entropy, generating 1 billion UUIDs per second for 85 years produces a 50% chance of a single collision. In practice, collision is a non-concern for any realistic use case.

The database problem: B-tree indexes (used by every major relational database) work best when new values are inserted in order or near-sequentially. UUID v4 inserts at random positions:

Existing index pages: [001...] [234...] [567...] [89a...]
New UUID v4: "a3f9..." β†’ inserts in the [89a...] page β†’ page may be full β†’ split

In the next write:
New UUID v4: "12c4..." β†’ inserts in [001...] page β†’ different page β†’ 50-75% page utilisation

On a high-write workload, a UUID v4 primary key table fragments rapidly β€” each insert hits a random page, those pages are often partially empty, and the total index size bloats significantly. Benchmarks show UUID v4 primary keys producing 20–50% more disk usage and significantly higher write amplification vs sequential IDs on MySQL InnoDB and PostgreSQL B-tree indexes.


UUID v7: time-ordered with random suffix

UUID v7 (ratified in RFC 9562, 2024) uses a Unix millisecond timestamp in the most significant bits:

[48-bit Unix timestamp ms][4-bit version=0111][12-bit random][2-bit variant][62-bit random]

A UUID v7 generated at 2024-11-15 14:00:00.000 UTC: 01934a8c-b400-7xxx-xxxx-xxxxxxxxxxxx

The 01934a8c-b400 prefix is the timestamp. UUIDs generated at the same millisecond have the same prefix and are ordered among themselves by their random suffix.

The database benefit: new rows insert at the end (or near the end) of the index. Pages fill sequentially. Write amplification drops dramatically. The improvement is comparable to using an auto-increment integer.

Adoption: UUID v7 support is still being added to libraries and databases. PostgreSQL 17 (2024) added native UUID v7 support via the uuidv7() function.


ULID: URL-friendly, sortable, case-insensitive

ULID (Universally Unique Lexicographically Sortable Identifier) was designed before UUID v7 standardisation to solve the same sorting problem:

01ARZ3NDEKTSV4RRFFQ69G5FAV
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  10-char time  16-char random
  (48-bit ms)   (80 bits)

Format: 26 characters of Crockford's Base32 (0-9, A-Z excluding I, L, O, U to avoid visual ambiguity). Case-insensitive. No hyphens.

Properties:

  • Lexicographically sortable (string sort = time sort)
  • 128-bit total (same as UUID)
  • 48-bit millisecond timestamp (same as UUID v7)
  • 80 bits of randomness (vs UUID v7's 74 bits β€” slightly more entropy)
  • URL-safe, no encoding needed
  • Can be stored as UUID in databases that understand the binary format

When ULID wins over UUID v7: when you need the identifier to be visually sortable in logs and URLs without hyphen parsing, and case-insensitivity is useful.


NanoID: compact, customisable, URL-safe

NanoID generates identifiers from a customisable alphabet using secure randomness:

Default (21 chars, 64-character alphabet):
V1StGXR8_Z5jdHi6B-myT

Custom 10-char numeric:
8372910456

Default parameters: 21 characters from A-Za-z0-9_-. This provides approximately 126 bits of entropy β€” comparable to UUID v4.

Why 21 characters? 64-character alphabet = 6 bits per character. 21 Γ— 6 = 126 bits β‰ˆ UUID v4's 122 bits.

Collision calculator: 1 - e^(-(nΒ²/2Γ—64Β²ΒΉ)) where n = number of IDs generated. NanoID has a collision calculator at zelark.github.io/nano-id-cc/. At 1,000 IDs/second for 100 years: probability 0.000000009% β€” negligible.

Custom alphabet use cases:

const { customAlphabet } = require('nanoid');

// Short numeric-only ID (9 chars, 30 bits)
const shortId = customAlphabet('1234567890', 9);
shortId() // '914856201'

// Human-friendly (no 0/O, 1/l ambiguity)
const humanId = customAlphabet('23456789abcdefghjkmnpqrstuvwxyz', 10);
humanId() // 'n4zr9h5qw2'

// URL slug ID
const slug = customAlphabet('abcdefghijklmnopqrstuvwxyz', 6);
slug() // 'kdnpxt'

When NanoID wins: shorter than UUID (21 vs 36 chars), URL-safe by default, no hyphens, customisable length for the exact entropy you need.


Comparison summary

Format Length Sortable Entropy DB-friendly Use when
UUID v4 36 chars No 122 bits Poor (fragmentation) Legacy/compatibility requirements
UUID v7 36 chars Yes (time-ordered) 74 bits Excellent New systems requiring UUID compatibility
ULID 26 chars Yes 80 bits Excellent Log/URL sortability; no hyphens
NanoID 21 chars No 126 bits Same as UUID v4 Short URLs, slugs, custom alphabets
CUID2 24 chars Yes (partial) ~128 bits Good Collision-resistant IDs in distributed systems

How to use the Random String Generator on sadiqbd.com

  1. Generate random strings for any identifier use case
  2. Custom alphabet β€” restrict to URL-safe characters or specific character sets
  3. Set exact length β€” for known-entropy identifiers
  4. Use for: API keys, session tokens, short URLs, slug suffixes, nonce values

Frequently Asked Questions

Can I use UUID v7 with an existing UUID v4 database column? Yes β€” UUID v7 is still a valid UUID. Any column defined as UUID or CHAR(36) accepts UUID v7 values without schema changes. The improvement is immediate: new rows get time-ordered UUIDs; old rows keep their random v4 values. The index won't fully defragment until the old v4 rows are removed, but writes improve immediately.

What is CUID2 and when should I use it? CUID2 (Collision-resistant Unique ID) is a newer format designed for distributed systems where multiple nodes generate IDs simultaneously. It includes a fingerprint of the generating machine, a timestamp, and a random component. Slightly longer than NanoID but designed to be collision-resistant across distributed generation without coordination.

Is the Random String Generator free? Yes β€” completely free, no sign-up required.

Try the Random String Generator free at sadiqbd.com β€” generate secure random strings of any length in any character set.

Share:
Try the related tool:
Open Random String Generator

More Random String Generator articles