Last Updated: 3/9/2026
Collision Probability
Understanding collision probability helps you choose the right ID size for your use case.
What is a Collision?
A collision occurs when two generated IDs are identical:
import { nanoid } from 'nanoid'
const id1 = nanoid()
const id2 = nanoid()
if (id1 === id2) {
// Collision! (extremely unlikely with default settings)
}Birthday Paradox
Collision probability follows the birthday problem :
In a room of 23 people, there’s a 50% chance two share a birthday.
Similarly, with IDs:
With N possible IDs, collisions become likely much sooner than you’d expect.
Mathematical Formula
P(collision) ≈ (n² / 2) × (1 / total_combinations)
Where:
- n = number of IDs generated
- total_combinations = alphabet_size ^ id_lengthExample Calculation
Default Nano ID (21 chars, 64-char alphabet):
Total combinations = 64^21 = 2^126 ≈ 8.5 × 10^37
For 1 billion IDs:
P(collision) ≈ (10^9)² / (2 × 2^126)
≈ 10^18 / 2^127
≈ 0.00000000000000001%Collision Probability Tables
Default Nano ID (21 chars)
| IDs Generated | Collision Probability |
|---|---|
| 1,000 | 0.000000000000000000000000000000001% |
| 1,000,000 | 0.0000000000000000000000001% |
| 1,000,000,000 | 0.00000000000000001% |
| 1,000,000,000,000 | 0.000000000001% |
| 103,000,000,000,000 | 0.0000001% (1 in billion) |
Size Comparison
| ID Size | Bits | IDs for 1% Collision |
|---|---|---|
| 6 | 36 | ~68,000 |
| 8 | 48 | ~16 million |
| 10 | 60 | ~1 billion |
| 12 | 72 | ~4 trillion |
| 16 | 96 | ~4 quintillion |
| 21 | 126 | ~2.8 × 10^18 |
| 32 | 192 | ~1.9 × 10^28 |
Alphabet Size Impact
| Alphabet | Size | 10-char ID | 15-char ID | 20-char ID |
|---|---|---|---|---|
| Binary | 2 | 1,024 | 32,768 | 1 million |
| Decimal | 10 | 10 billion | 1 quadrillion | 100 quintillion |
| Hex | 16 | 1 trillion | 1 quintillion | 1 nonillion |
| Alphanumeric | 36 | 3.6 trillion | 221 sextillion | 13 octillion |
| Default | 64 | 1.2 quadrillion | 1.2 nonillion | 1.2 tredecillion |
Using the Calculator
Use the online calculator to check your configuration:
Steps
- Enter alphabet size (e.g., 64 for default)
- Enter ID size (e.g., 21 for default)
- Enter expected IDs (e.g., 1,000,000)
Example Results
Configuration: 10 chars, 64-char alphabet, 1 million IDs
Total combinations: 64^10 = 1.15 × 10^18
Collision probability: ~0.000043%
Safe: Yes ✅Configuration: 8 chars, 10-char alphabet (digits), 100,000 IDs
Total combinations: 10^8 = 100,000,000
Collision probability: ~5%
Safe: No ⚠️ (consider 10 chars)Practical Guidelines
When is it Safe?
General rule: Collision probability should be <0.001% (1 in 100,000)
import { nanoid } from 'nanoid'
// ✅ Safe: Default settings
const id = nanoid() // 21 chars, <0.000000000000001% for 1B IDs
// ⚠️ Check: Shorter IDs
const shortId = nanoid(10) // ~0.1% for 1B IDs (borderline)
// ❌ Unsafe: Very short IDs
const tinyId = nanoid(6) // ~1.5% for 1M IDs (too high!)Recommended Sizes
| Use Case | IDs Expected | Recommended Size |
|---|---|---|
| Small app | <10,000 | 8 chars |
| Medium app | <1 million | 10 chars |
| Large app | <1 billion | 12-14 chars |
| Enterprise | <1 trillion | 16-18 chars |
| Default | Any reasonable | 21 chars (UUID equivalent) |
Comparison with UUID
UUID v4
Format: "f47ac10b-58cc-4372-a567-0e02b2c3d479"
Bits: 122 (6 bits reserved)
Collision for 1B IDs: ~0.0000000000000000001%Nano ID (default)
Format: "V1StGXR8_Z5jdHi6B-myT"
Bits: 126
Collision for 1B IDs: ~0.00000000000000001%Conclusion: Similar collision resistance, but Nano ID is shorter (21 vs 36 chars).
Real-World Examples
Example 1: E-commerce Orders
Requirements:
- 1 million orders/year
- 10-year lifespan
- Total: 10 million orders
Calculation:
import { nanoid } from 'nanoid'
// Option 1: 10 chars
const orderId = nanoid(10)
// Collision probability: ~0.0043% ✅
// Option 2: 12 chars (safer)
const safeOrderId = nanoid(12)
// Collision probability: ~0.000001% ✅✅Example 2: URL Shortener
Requirements:
- 100 billion URLs
- Short as possible
Calculation:
import { customAlphabet } from 'nanoid'
// Alphanumeric (62 chars)
const nanoid = customAlphabet(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
8
)
// 62^8 = 218 trillion combinations
// For 100B URLs: ~2.3% collision ⚠️
// Better: 9 chars
const saferNanoid = customAlphabet(
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
9
)
// 62^9 = 13.5 quadrillion combinations
// For 100B URLs: ~0.037% collision ✅Example 3: Session IDs
Requirements:
- 1 million concurrent sessions
- High security
Calculation:
import { nanoid } from 'nanoid'
// Default: 21 chars
const sessionId = nanoid()
// Collision probability: ~0.0000000000000001% ✅✅✅
// Or longer for extra security
const secureSessionId = nanoid(32)
// Collision probability: negligible ✅✅✅✅When to Worry
⚠️ Warning Signs
- Collision probability >0.01% (1 in 10,000)
- Short IDs (<8 chars) with high volume
- Small alphabets (e.g., digits only) with many IDs
- Production database already has collisions
❌ Danger Zone
- Collision probability >1%
- Very short IDs (≤6 chars) with >10,000 IDs
- Binary/ternary alphabets
Mitigation Strategies
1. Increase ID Length
// Before: 8 chars, ~5% collision for 100K IDs
const shortId = nanoid(8)
// After: 10 chars, ~0.1% collision for 100K IDs
const longerId = nanoid(10)2. Use Larger Alphabet
// Before: 10 chars, 0-9 only (10 billion combinations)
const numeric = customAlphabet('0123456789', 10)
// After: 10 chars, alphanumeric (3.6 trillion combinations)
const alphanum = customAlphabet(
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
10
)3. Add Collision Detection
import { nanoid } from 'nanoid'
async function createUniqueId(db, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const id = nanoid(10)
const exists = await db.exists(id)
if (!exists) return id
}
throw new Error('Failed to generate unique ID')
}4. Use Composite Keys
import { nanoid } from 'nanoid'
// Combine with timestamp for uniqueness
const id = `${Date.now()}-${nanoid(8)}`
// Example: "1709984567890-V1StGXR8"