You need a unique ID. Should you use UUID or NanoID? How do you generate them? When should you use each? Here's the complete guide.
Why Use UUIDs or NanoIDs?
- Database primary keys — Distributed systems without coordinating IDs
- API resource IDs — Unpredictable, harder to enumerate
- Session tokens — Unique, non-guessable sessions
- Tracking IDs — Correlate requests across systems
UUID (Universally Unique Identifier)
Format
128-bit number, usually displayed as 36-character string:
550e8400-e29b-41d4-a716-446655440000
UUID Versions
UUID v1 (Time-based)- Generated from timestamp + MAC address
- Sequential, somewhat predictable
- Reveals system info (MAC address)
- Don't use for security-sensitive IDs
- 128 bits of random data
- Unpredictable, secure
- Most common for user-facing IDs
- Large chance of collisions in very large datasets (negligible)
- Generated from namespace + name (deterministic)
- Same input = same UUID
- Good for reproducible, namespaced IDs
UUID Pros
- Industry standard, supported everywhere
- Large number space (2^128 ≈ 5.3 × 10^36)
- Collision risk negligible
UUID Cons
- 36 characters (long in URLs, databases)
- Randomly generated (not sortable)
- Bad for database indexing (random writes)
NanoID
Format
21-character URL-friendly string:
V1StGXR_Z5j3ewhQQKgQw
Why NanoID?
Created to fix UUID shortcomings:
- Smaller (21 chars vs 36)
- URL-safe (no hyphens or special chars)
- Faster generation
- Easier to say/type
NanoID Pros
- Short (21 vs 36 characters)
- URL-safe (no special encoding needed)
- Sortable (can be generated with prefix)
- Faster to generate
NanoID Cons
- Newer, less universal support
- Slightly smaller number space (still safe for collisions)
Generating UUIDs
JavaScript/Node.js
// Using uuid package
const { v4: uuidv4 } = require('uuid');
const id = uuidv4(); // "550e8400-e29b-41d4-a716-446655440000"
// Using Web Crypto (native)
const id = crypto.randomUUID();
// Using NanoID
const { nanoid } = require('nanoid');
const id = nanoid(); // "V1StGXR_Z5j3ewhQQKgQw"
Python
import uuid
# UUID v4
id = uuid.uuid4() # Returns UUID object
print(str(id)) # "550e8400-e29b-41d4-a716-446655440000"
# Using nanoid package
from nanoid import generate
id = generate() # "V1StGXR_Z5j3ewhQQKgQw"
PHP
// UUID v4
$id = RamseyUuidUuid::uuid4()->toString();
// Using NanoID alternative (Ulid)
$ulid = new UlidUlid();
Our UUID/NanoID Generator
Use our UUID/NanoID Generator:
- Choose UUID version or NanoID
- Generate IDs instantly
- Copy and use
- Generate batch
When to Use Each
Use UUID v4 when:- You need standard industry format
- Working with systems that require UUID
- Don't care about string length
- You want shorter IDs (URLs, display)
- Generating many IDs (faster)
- URL-friendly format matters
- You need temporal ordering (rarely)
- Don't care about leaking MAC address (very rare)
- Avoid for new applications
Database Considerations
UUID as Primary Key
Pros: Distributed generation, no sequences
Cons: Bad indexing (random), 16 bytes storage
Better approach: Use ULID or sortable NanoID for better indexing:
// ULID (sortable UUID replacement)
new ULID() // "01ARZ3NDEKTSV4RRFFQ69G5FAV"
UUID vs Integer ID
-- Integer ID (4-8 bytes)
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) UNIQUE
);
-- UUID (16 bytes)
CREATE TABLE users (
id CHAR(36) PRIMARY KEY,
email VARCHAR(255) UNIQUE
);
-- ULID (sortable, 16 bytes)
CREATE TABLE users (
id CHAR(26) PRIMARY KEY,
email VARCHAR(255) UNIQUE
);
Security Considerations
Randomness Is Critical
UUIDs and NanoIDs must use cryptographically secure random sources:
// ✓ Secure
crypto.randomUUID()
// ✗ Insecure
Math.random().toString(36) // Predictable
Don't Use Sequential IDs for Sensitive Resources
Sequential IDs (1, 2, 3...) allow enumeration attacks. Use UUID/NanoID instead.
Real-World Usage
API Resource IDs
GET /api/users/550e8400-e29b-41d4-a716-446655440000
GET /api/posts/V1StGXR_Z5j3ewhQQKgQw
Session Tokens
Set-Cookie: sessionId=550e8400-e29b-41d4-a716-446655440000
Tracking IDs
X-Request-ID: V1StGXR_Z5j3ewhQQKgQw
Pro Tips
- Use UUID v4 or NanoID for general purposes
- Use ULID for sortable IDs in databases
- Never rely on sequential IDs for security
- Always use cryptographic randomness
- Test collision rates for very large datasets
Collision Probabilities
GET /api/users/550e8400-e29b-41d4-a716-446655440000
GET /api/posts/V1StGXR_Z5j3ewhQQKgQwSet-Cookie: sessionId=550e8400-e29b-41d4-a716-446655440000X-Request-ID: V1StGXR_Z5j3ewhQQKgQwEven with huge datasets, collision risk is negligible:
- UUID v4: Collision after 2.71 × 10^18 IDs
- NanoID: Collision after 8.03 × 10^15 IDs
For context: generating 1 million IDs per second would take billions of years.
Conclusion
Both UUIDs and NanoIDs solve the problem of unique ID generation. UUID is industry standard, NanoID is modern and compact. Pick based on your needs: standard support (UUID) or shorter IDs (NanoID). Use our generator for instant IDs.
Comments
Leave a Comment
No comments yet. Be the first to comment!