Skip to Content
advanced-topicsCollision Probability

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_length

Example 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 GeneratedCollision Probability
1,0000.000000000000000000000000000000001%
1,000,0000.0000000000000000000000001%
1,000,000,0000.00000000000000001%
1,000,000,000,0000.000000000001%
103,000,000,000,0000.0000001% (1 in billion)

Size Comparison

ID SizeBitsIDs for 1% Collision
636~68,000
848~16 million
1060~1 billion
1272~4 trillion
1696~4 quintillion
21126~2.8 × 10^18
32192~1.9 × 10^28

Alphabet Size Impact

AlphabetSize10-char ID15-char ID20-char ID
Binary21,02432,7681 million
Decimal1010 billion1 quadrillion100 quintillion
Hex161 trillion1 quintillion1 nonillion
Alphanumeric363.6 trillion221 sextillion13 octillion
Default641.2 quadrillion1.2 nonillion1.2 tredecillion

Using the Calculator

Use the online calculator  to check your configuration:

Steps

  1. Enter alphabet size (e.g., 64 for default)
  2. Enter ID size (e.g., 21 for default)
  3. 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!)
Use CaseIDs ExpectedRecommended Size
Small app<10,0008 chars
Medium app<1 million10 chars
Large app<1 billion12-14 chars
Enterprise<1 trillion16-18 chars
DefaultAny reasonable21 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"

See Also