UUID Alternatives: ULID, NanoID, CUID, and Short UUID Compared
Meta Description: Compare UUID alternatives like ULID, NanoID, CUID, and short UUID. Find the best unique identifier format for your use case with this complete comparison guide.
UUIDs work great. But 36 characters is a lot for a URL. And random v4 UUIDs don't sort. And sometimes you need something more readable.
Enter the alternatives: ULID, NanoID, CUID, and short UUID formats. Each solves specific problems UUIDs don't. Here's how to choose.
Why Look Beyond UUID?
UUIDs have real limitations:
| Issue | Description |
|---|---|
| Length | 36 characters with hyphens |
| URL-unfriendly | Hyphens complicate URLs |
| Not sortable | v4 is random, no time ordering |
| Not human-readable | Hard to distinguish at a glance |
| Case handling | Some systems normalize case inconsistently |
These alternatives address one or more of these issues.
ULID: Universally Unique Lexicographically Sortable Identifier
What Is It?
ULID = Timestamp (48 bits) + Randomness (80 bits)
01ARZ3NDEKTSV4RRFFQ69G5FAV
├─────────┤├────────────────┤
timestamp randomness
(10) (16)
Key Features
| Feature | Value |
|---|---|
| Length | 26 characters |
| Encoding | Crockford Base32 (no ambiguous chars) |
| Sortable | Yes, lexicographically |
| Monotonic option | Within same millisecond |
| Case insensitive | Yes |
| Timestamp extractable | Yes |
ULID vs UUID
| Aspect | UUID v4 | ULID |
|---|---|---|
| Length | 36 chars | 26 chars |
| Sortable | No | Yes |
| URL safe | No (hyphens) | Yes |
| Case sensitive | Usually yes | No |
| Entropy | 122 bits | 80 bits |
| Database friendly | Depends | Excellent |
When to Use ULID
- ✅ Need sortable IDs
- ✅ URLs or user-facing IDs
- ✅ Database primary keys
- ✅ Distributed systems
- ❌ Need maximum entropy (use UUID v4)
Generate ULID
// JavaScript
import { ulid } from 'ulid';
const id = ulid();
// 01ARZ3NDEKTSV4RRFFQ69G5FAV
# Python
import ulid
id = ulid.new()
print(id.str)
# 01ARZ3NDEKTSV4RRFFQ69G5FAV
NanoID: Compact, Fast, URL-Safe
What Is It?
NanoID is a tiny (130 bytes), fast, URL-friendly unique ID generator.
V1StGXR8_Z5jdHi6B-myT
Key Features
| Feature | Value |
|---|---|
| Default length | 21 characters |
| Alphabet | A-Za-z0-9_- (URL-safe) |
| Customizable | Length and alphabet |
| Collision resistant | At 1000 IDs/hour, 1% collision in ~149 years |
| No dependencies | Zero |
| Size | 130 bytes (gzipped) |
NanoID vs UUID
| Aspect | UUID v4 | NanoID |
|---|---|---|
| Length | 36 chars | 21 chars (default) |
| URL safe | No | Yes |
| Customizable | No | Yes (length, alphabet) |
| Entropy | 122 bits | ~126 bits (21 chars) |
| Bundle size | N/A | Tiny (130 bytes) |
When to Use NanoID
- ✅ Frontend-generated IDs
- ✅ URLs and slugs
- ✅ Need small bundle size
- ✅ Custom alphabet requirements
- ❌ Need timestamp/sortability
Generate NanoID
// JavaScript
import { nanoid } from 'nanoid';
const id = nanoid();
// V1StGXR8_Z5jdHi6B-myT
// Custom length
const short = nanoid(10);
// IRFa-VaY2b
// Custom alphabet
import { customAlphabet } from 'nanoid';
const numbers = customAlphabet('1234567890', 12);
numbers();
// 374185294637
# Python
from nanoid import generate
id = generate()
# V1StGXR8_Z5jdHi6B-myT
CUID / CUID2: Collision-Resistant IDs
What Is It?
CUID (Collision-resistant Unique Identifier) is designed for horizontal scaling without coordination.
CUID (v1):
ch72gsb320000udocl363eofy
CUID2 (recommended):
tz4a98xxat96iws9zmbrgj3a
Key Features
| Feature | CUID2 |
|---|---|
| Length | 24 characters (default) |
| Encoding | Lowercase a-z0-9 |
| Collision resistant | Designed for distributed systems |
| Monotonic | Within same process |
| Fingerprinting | Includes machine fingerprint |
| Security | Resistant to enumeration |
CUID vs UUID
| Aspect | UUID v4 | CUID2 |
|---|---|---|
| Length | 36 chars | 24 chars |
| Case | Mixed | Lowercase only |
| Sortable | No | Partially (time component) |
| Distributed-safe | Yes | Extra guarantees |
| Security focus | Low | High |
When to Use CUID
- ✅ Distributed systems without coordination
- ✅ Security-sensitive applications
- ✅ Need lowercase-only IDs
- ✅ Horizontal scaling
- ❌ Need strict time ordering
Generate CUID
// JavaScript
import { createId } from '@paralleldrive/cuid2';
const id = createId();
// tz4a98xxat96iws9zmbrgj3a
# Python
from cuid2 import cuid_wrapper
cuid_generator = cuid_wrapper()
id = cuid_generator()
# tz4a98xxat96iws9zmbrgj3a
Short UUID: Human-Readable UUIDs
What Is It?
Short UUID encodes standard UUIDs in a more compact format.
Standard UUID:
f47ac10b-58cc-4372-a567-0e02b2c3d479
Short UUID (Base57):
mhvXdrZT4jP5T8vBxuvm75
Key Features
| Feature | Value |
|---|---|
| Length | 22 characters (typical) |
| Reversible | Yes, converts back to full UUID |
| Compatible | Works with any UUID |
| Alphabet options | Base57, Base58, custom |
When to Use Short UUID
- ✅ Need UUID compatibility but shorter format
- ✅ Existing UUID infrastructure
- ✅ Human-readable URLs
- ✅ QR codes (less data = faster scanning)
Generate Short UUID
// JavaScript
import short from 'short-uuid';
const translator = short();
// Generate
const shortId = translator.new();
// mhvXdrZT4jP5T8vBxuvm75
// Convert existing UUID
const fromUuid = translator.fromUUID('f47ac10b-58cc-4372-a567-0e02b2c3d479');
// mhvXdrZT4jP5T8vBxuvm75
// Convert back
const uuid = translator.toUUID(shortId);
// f47ac10b-58cc-4372-a567-0e02b2c3d479
Complete Comparison Table
| Feature | UUID v4 | ULID | NanoID | CUID2 | Short UUID |
|---|---|---|---|---|---|
| Length | 36 | 26 | 21 | 24 | 22 |
| Sortable | ❌ | ✅ | ❌ | ⚠️ | ❌ |
| URL-safe | ❌ | ✅ | ✅ | ✅ | ✅ |
| Case-sensitive | ⚠️ | ❌ | ✅ | ❌ | ✅ |
| Customizable | ❌ | ❌ | ✅ | ⚠️ | ✅ |
| Entropy (bits) | 122 | 80 | 126 | ~104 | 122 |
| Timestamp | ❌ | ✅ | ❌ | ⚠️ | ❌ |
| UUID compatible | ✅ | ❌ | ❌ | ❌ | ✅ |
| DB optimized | ❌ | ✅ | ❌ | ✅ | ❌ |
Decision Matrix
Choose UUID v4 When:
- Maximum compatibility required
- Standard libraries only
- Entropy is critical
- Not concerned about length
Choose ULID When:
- Need sortable IDs
- Database primary keys
- Time-series data
- 26 characters acceptable
Choose NanoID When:
- Shortest possible IDs
- Custom alphabets needed
- Frontend generation
- Bundle size matters
Choose CUID2 When:
- Distributed systems
- Security-first applications
- Lowercase-only requirement
- Need fingerprinting
Choose Short UUID When:
- Must maintain UUID compatibility
- Existing UUID infrastructure
- Need reversible encoding
- URLs with UUIDs
Generate Any Format
Use our generators:
- UUID Generator — Classic v4, v7 UUIDs
- ULID Generator — Sortable, 26-character IDs
- NanoID Generator — Compact, customizable IDs
FAQ
Which has the lowest collision probability?
UUID v4 and NanoID (21 chars) have ~126 bits of entropy. ULID has 80 bits random (timestamp adds uniqueness). All are effectively collision-proof for practical use.
Can I use these in databases?
Yes. ULID and CUID2 are specifically designed for database use. NanoID works but doesn't optimize for sorted inserts. Store as VARCHAR or TEXT.
Are these compatible with each other?
No. Each format is distinct. Short UUID is special—it encodes/decodes regular UUIDs, so it's UUID-compatible.
Which is best for URLs?
NanoID (shortest) or ULID (sortable). Both are URL-safe. CUID2 is lowercase, good for case-insensitive URLs.
Can I migrate from UUID to ULID?
Not directly—they're different formats. You'd need to:
- Add new ULID column
- Generate ULIDs for existing rows
- Update references
- Drop UUID column
Or maintain both columns during transition.
Related Tools:
- UUID Generator — Classic UUID generation
- ULID Generator — Sortable IDs
- NanoID Generator — Compact IDs