Why Unique Identifiers Matter
Every record in a database, every API resource, and every event in a distributed system needs a unique identifier. The choice of ID format has surprisingly far-reaching consequences for performance, security, and developer experience. A poorly chosen ID scheme can cause database index fragmentation, expose sequential record counts, or create URL-guessing vulnerabilities.
UUID — The Universal Standard
UUID (Universally Unique Identifier, RFC 9562) is a 128-bit identifier represented as 32 hexadecimal digits in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. There are several versions:
UUID v4 (Random)
122 bits of cryptographically random data, 6 bits reserved for version/variant. This is the most widely used UUID version.
550e8400-e29b-41d4-a716-446655440000 // Example UUID v4
Pros: Truly random, no information leakage, universally supported
Cons: Random order causes B-tree index fragmentation in databases (poor write performance at scale), not URL-friendly (hyphens), 36 characters
UUID v1 (Time-Based)
Combines a timestamp, MAC address, and clock sequence. The time component is embedded but scrambled across the UUID structure, making it partially sortable but not cleanly.
Cons: Exposes the generating machine's MAC address (privacy concern), not monotonically sortable
UUID v7 (Time-Ordered, New Standard)
UUID v7 was standardized in RFC 9562 (2024) and addresses the sortability problem of v4:
018e3a3c-b9d0-7b9a-8f2e-4a1b3c5d7e9f
// First 48 bits = millisecond Unix timestamp (sortable!)
// Remaining bits = random
UUID v7 combines the universality of UUID with time-ordering, making it ideal for database primary keys. It's gaining adoption as the recommended UUID version for new systems.
ULID — Sortable, Compact, and Readable
ULID (Universally Unique Lexicographically Sortable Identifier) was designed to solve UUID's sortability problem while improving human readability:
01ARZ3NDEKTSV4RRFFQ69G5FAV // 26 characters, Crockford Base32
ULID structure:
- First 10 characters — 48-bit millisecond timestamp (sorts lexicographically)
- Last 16 characters — 80 bits of randomness
Pros:
- Lexicographically sortable — records created later sort after earlier ones
- 26 characters (vs 36 for UUID) — more compact
- Case-insensitive, no hyphens — URL-friendly
- Monotonic within the same millisecond (some implementations)
Cons:
- Less universal library support than UUID
- Encodes timestamp — approximate creation time is visible
- Not an IETF standard (unlike UUID)
Nano ID — Compact, Configurable, URL-Safe
Nano ID is a small library that generates compact, cryptographically secure IDs:
V1StGXR8_Z5jdHi6B-myT // Default: 21 characters, URL-safe alphabet
Key characteristics:
- Default size: 21 characters using URL-safe characters (
A-Za-z0-9_-) - Collision probability: At 21 chars, ~1% chance of collision after generating 149 billion IDs
- Configurable: Size and alphabet are customizable
- Secure: Uses
crypto.getRandomValues()/crypto.randomBytes()
Pros: Extremely compact, URL-safe by default, configurable length, tiny package size
Cons: Not time-ordered, no standardized format, not database-index-friendly (random order)
Comparison Table
| Property | UUID v4 | UUID v7 | ULID | Nano ID |
|---|---|---|---|---|
| Length | 36 chars | 36 chars | 26 chars | 21 chars (default) |
| Sortable by time | No | Yes | Yes | No |
| URL-safe | No (hyphens) | No (hyphens) | Yes | Yes |
| Standardized | RFC 9562 | RFC 9562 | Spec only | No |
| DB index friendly | Poor | Good | Good | Poor |
| Encodes timestamp | No | Yes | Yes | No |
| Library support | Universal | Growing | Good | Good |
Database Performance: Why Sortability Matters
Most databases use B-tree indexes for primary keys. Random UUIDs (v4) cause index fragmentation because new records insert at random positions throughout the index tree, causing expensive page splits and leaving indexes partially empty. At high insert volume, this degrades write performance significantly.
UUID v7 and ULID solve this by generating IDs that are monotonically increasing over time. New records always append to the end of the index, like auto-increment integers — but globally unique across distributed systems.
Decision Guide
| Use case | Recommended |
|---|---|
| Database primary keys (high write volume) | UUID v7 or ULID |
| Database primary keys (standard volume) | UUID v4 or v7 |
| API resource IDs (in URLs) | Nano ID or ULID |
| Cross-system interoperability | UUID v4 (universal support) |
| Short-lived tokens (session, CSRF) | Nano ID (compact) |
| Event sourcing, time-ordered logs | ULID or UUID v7 |
| File names, identifiers in filenames | Nano ID (URL-safe) |
Generate UUIDs in Your Browser
Use the Copynix UUID Generator to generate bulk UUID v4 values instantly in your browser using crypto.randomUUID(). All IDs are generated locally — nothing is transmitted to any server. Useful for seeding test data, generating API keys for testing, or populating configuration files.
Summary
For most new systems: use UUID v7 if you need a standard, or ULID if you want better readability and URL-safety. Use UUID v4 when compatibility with existing systems is paramount. Use Nano ID when compactness and URL-safety matter more than time ordering. The worst choice is auto-increment integers for distributed systems — unique IDs must be collision-resistant without coordination.
