← Blog
UtilitiesApril 18, 202410 min

UUID v4, ULID, and NanoID: Choosing the Right Unique Identifier

Compare the most popular unique identifier formats — their structure, trade-offs, and which to reach for in different situations.

Why Not Just Use Auto-Increment IDs?

Auto-increment integer IDs (1, 2, 3…) work well in single-database systems. They break down when you need to:

  • Generate IDs client-side before a database round-trip
  • Merge records from multiple databases without collisions
  • Avoid exposing record counts or insertion order to users
  • Work in distributed or eventually-consistent systems

UUID, ULID, and NanoID all address these concerns in different ways.

UUID v4

UUID (Universally Unique Identifier) is defined by RFC 4122. Version 4 is randomly generated — 122 bits of random data with 6 bits reserved for version and variant markers.

// Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
// Where y is 8, 9, a, or b

550e8400-e29b-41d4-a716-446655440000
f47ac10b-58cc-4372-a567-0e02b2c3d479

Generating UUID v4 in the browser

// Modern — cryptographically secure
const id = crypto.randomUUID();

// Older fallback
function uuid() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = crypto.getRandomValues(new Uint8Array(1))[0] % 16;
    return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
  });
}

UUID v4 trade-offs

  • Pro — Universally standardized, supported everywhere
  • Pro — Practically zero collision probability (2¹²² combinations)
  • Con — Random order hurts database B-tree index performance at scale
  • Con — 36 characters (with hyphens) is verbose in URLs and logs

ULID (Universally Unique Lexicographically Sortable Identifier)

ULID was designed to address UUID's random ordering problem. Each ULID encodes a millisecond-precision timestamp in the first 48 bits, followed by 80 random bits.

01ARZ3NDEKTSV4RRFFQ69G5FAV

// Structure:
// 01ARZ3NDEK   — timestamp (10 chars, 48 bits)
// TSV4RRFFQ69G5FAV — randomness (16 chars, 80 bits)
  • Pro — Lexicographically sortable (newer IDs sort after older ones)
  • Pro — 26 characters vs 36 for UUID
  • Pro — Better database index locality than UUID v4
  • Con — Not natively supported in browsers; needs a library
  • Con — Encodes creation time, which may be a privacy concern

NanoID

NanoID is a small, URL-friendly unique ID library. By default it generates 21 characters using a 64-character alphabet, giving ~126 bits of randomness — comparable to UUID v4.

// Default 21-char output
V1StGXR8_Z5jdHi6B-myT

// Custom length and alphabet
nanoid(10)           // Shorter, less entropy
nanoid(32, '0123456789abcdef')  // Hex only
  • Pro — URL-safe by default (no special characters)
  • Pro — Configurable length and alphabet
  • Pro — Tiny library (~130 bytes minified)
  • Con — Not a standard; not natively supported
  • Con — Random order (same B-tree issue as UUID v4)

UUID v7 — The Best of Both Worlds

UUID v7 (RFC 9562, 2024) is a newer standard that combines a millisecond timestamp prefix with random bits — giving sortability like ULID while staying within the UUID standard. It is becoming the preferred choice for new database schemas.

// UUID v7 format: timestamp-first
018e57e4-4a0b-7000-b3d9-47c44b2bfc44
// First 12 hex chars = Unix ms timestamp

Quick Decision Guide

  • UUID v4 — Default choice; works everywhere; no dependency needed
  • UUID v7 — New projects where database index performance matters
  • ULID — When you need sortability and can add a small dependency
  • NanoID — Short, URL-safe IDs (session tokens, short links)
  • Auto-increment — Simple CRUD apps with a single database

Generate UUIDs instantly

Use our free UUID Generator to create UUID v4 strings in bulk — copy individually or all at once.

Open UUID Generator →