EVMTools

UUID vs NanoID

Compare UUID and NanoID: format, collision probability, performance, size, and which unique identifier to use for your project.

Every application needs unique identifiers. UUID (Universally Unique Identifier) has been the standard since 2005, generating 128-bit IDs in a familiar 8-4-4-4-12 hexadecimal format. NanoID is a modern alternative that produces shorter, URL-friendly IDs with comparable collision resistance and better performance. This guide provides a detailed comparison to help you choose the right one for your project.

What They Look Like

UUID v4:  550e8400-e29b-41d4-a716-446655440000
          (36 characters with hyphens, 32 hex digits)

NanoID:   V1StGXR8_Z5jdHi6B-myT
          (21 characters, URL-safe alphabet)

UUID v7:  018f3e5c-8b00-7000-8000-000000000001
          (36 characters, time-sortable)

ULID:     01ARZ3NDEKTSV4RRFFQ69G5FAV
          (26 characters, time-sortable)

Generate UUIDs instantly with our UUID Generator.

UUID vs NanoID: Comparison Table

FeatureUUID v4NanoID (default)
String length36 characters (with hyphens)21 characters
Random bits122 bits~126 bits
Alphabet0-9, a-f (hex) + hyphensA-Z, a-z, 0-9, _, - (64 chars)
URL safeNo (hyphens are safe, but it is long)Yes (designed for URLs)
SortableNo (random)No (random)
StandardRFC 9562 (was RFC 4122)No formal standard
Native supportMost languages, databases, ORMsnpm package (JavaScript/TS focused)
Bundle size (JS)~7 KB (uuid package)~130 bytes
Performance (Node.js)~1M ops/sec~3M ops/sec
Custom alphabetNo (fixed hex format)Yes (configurable)

How UUID v4 Works

UUID v4 generates 128 bits of data, of which 122 are random. The remaining 6 bits encode the version (4) and variant (RFC 4122):

UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx

  "4" = version 4 (random)
  "y" = variant bits (8, 9, a, or b)

Example: 550e8400-e29b-41d4-a716-446655440000
                        ^    ^
                    version  variant

Total: 128 bits = 32 hex digits
Random: 122 bits (6 bits reserved for version + variant)
Collision space: 2^122 ≈ 5.3 × 10^36

UUIDs are universally supported. Every major programming language has a built-in or standard library UUID implementation. Databases like PostgreSQL have native UUID column types with optimized storage (16 bytes internally, regardless of the 36-character string representation).

How NanoID Works

NanoID generates a string of random characters from a configurable alphabet. The default configuration uses a 64-character URL-safe alphabet and produces 21-character IDs:

Default alphabet: A-Za-z0-9_-  (64 characters = 6 bits per char)
Default length:   21 characters
Entropy:          21 × 6 = 126 bits
Collision space:  2^126 ≈ 8.5 × 10^37

// Usage in JavaScript
import { nanoid } from 'nanoid';
const id = nanoid();      // "V1StGXR8_Z5jdHi6B-myT" (21 chars)
const short = nanoid(10); // "IRFa-VaY2b" (10 chars, less entropy)

// Custom alphabet
import { customAlphabet } from 'nanoid';
const numericId = customAlphabet('0123456789', 12);
numericId(); // "839462847592"

The key advantage is flexibility: you control the alphabet and length, tuning the tradeoff between collision resistance and ID size for your specific needs.

Collision Probability

Both UUID v4 and default NanoID have collision probabilities that are effectively zero for any practical application. Here is a comparison at different scales:

IDs GeneratedUUID v4 (122 bits)NanoID 21 (~126 bits)NanoID 10 (~60 bits)
1 million~10^-25~10^-26~10^-7
1 billion~10^-19~10^-20~0.4 (dangerous!)
1 trillion~10^-13~10^-14~1.0 (guaranteed)
1 quintillion~10^-1~10^-2N/A

Default NanoID (21 chars) actually has slightly more entropy than UUID v4. The danger zone is with shorter NanoIDs: a 10-character NanoID has only ~60 bits of entropy, which is not safe for large-scale applications. Always calculate the collision probability for your expected scale before shortening IDs.

Database Index Performance

Both UUID v4 and NanoID produce random IDs, which have a well-known problem with database B-tree indexes: new inserts land in random positions across the index, causing excessive page splits and poor cache utilization. This becomes a significant performance issue at scale.

For databases with millions of rows and high write throughput, consider time-sortable alternatives:

  • UUID v7: Embeds a Unix timestamp in the first 48 bits. New IDs are monotonically increasing, giving sequential B-tree inserts. Defined in RFC 9562 (2024).
  • ULID: 128-bit identifier with 48-bit timestamp + 80-bit randomness. Encoded as 26-character Crockford Base32 string. Lexicographically sortable.
  • Snowflake IDs: 64-bit IDs with timestamp + machine ID + sequence number. Used by Twitter, Discord, and Instagram.
  • CUID2: Secure, collision-resistant, time-sortable IDs designed for horizontal scaling.

For small-to-medium applications (under 10M rows), the B-tree performance difference is negligible. Choose based on other criteria first.

When to Use Each

Choose UUID When

  • Working with databases: PostgreSQL, MySQL, and most ORMs have native UUID support with optimized 16-byte binary storage. NanoID is stored as a variable-length string.
  • Cross-language systems: UUID is a universal standard recognized in every programming language and platform. NanoID is primarily a JavaScript ecosystem tool.
  • Enterprise and interoperability: APIs, SDKs, and protocols that expect UUID format. SOAP, SAML, and many enterprise standards require UUIDs.
  • You need v7 time-sortability: UUID v7 provides built-in time ordering without external libraries.

Choose NanoID When

  • URL-friendly IDs matter: Shorter IDs that look clean in URLs (/users/V1StGXR8_Z5jdHi6B-myT vs /users/550e8400-e29b-41d4-a716-446655440000).
  • Bundle size is critical: NanoID is ~130 bytes vs ~7KB for the uuid package. Matters for client-side JavaScript and edge functions.
  • Custom alphabet or length: Need numeric-only IDs, specific character sets, or non-standard lengths. NanoID's customAlphabet makes this trivial.
  • JavaScript/TypeScript projects: NanoID is the idiomatic choice in the Node.js and frontend ecosystem.

Code Examples

// UUID v4 in JavaScript
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4(); // "550e8400-e29b-41d4-a716-446655440000"

// UUID v4 (native, no library — Node.js 19.4+ / browsers)
const id = crypto.randomUUID(); // Built-in, no package needed!

// NanoID
import { nanoid } from 'nanoid';
const id = nanoid();     // "V1StGXR8_Z5jdHi6B-myT"
const short = nanoid(8); // "IRFa-VaY"

// NanoID with custom alphabet (e.g., no special characters)
import { customAlphabet } from 'nanoid';
const alphanumeric = customAlphabet(
  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
  12
);
const id = alphanumeric(); // "dK8JfN3mPxYq"

// Python
import uuid
id = str(uuid.uuid4())  # "550e8400-e29b-41d4-a716-446655440000"

# Python NanoID
from nanoid import generate
id = generate()  # "V1StGXR8_Z5jdHi6B-myT"

// Go
import "github.com/google/uuid"
id := uuid.New().String()  // "550e8400-e29b-41d4-a716-446655440000"

// Rust
use uuid::Uuid;
let id = Uuid::new_v4().to_string();

Note that crypto.randomUUID() is now built into modern JavaScript runtimes, eliminating the need for the uuid package entirely. This makes UUID v4 a zero-dependency option in modern environments.

The Full Landscape of ID Generators

ID TypeLengthSortableBest For
UUID v436 charsNoUniversal standard, cross-platform
UUID v736 charsYesDatabase PKs, time-ordered records
NanoID21 charsNoURL-friendly, JS apps, small payload
ULID26 charsYesTime-ordered, Crockford Base32
CUID224 charsYesDistributed systems, security
Snowflake~18 digitsYesHigh-throughput, coordinated systems

Frequently Asked Questions

What is the probability of a UUID collision?

For UUID v4, the probability of a collision is astronomically low. With 122 random bits, you would need to generate approximately 2.71 quintillion (2.71 x 10^18) UUIDs before having a 50% chance of a single collision. Generating 1 billion UUIDs per second, it would take about 85 years to reach a 50% collision probability. For practical purposes, UUID v4 collisions are considered impossible.

Is NanoID more secure than UUID?

Both UUID v4 and NanoID use cryptographically secure random number generators (crypto.getRandomValues in browsers, crypto.randomBytes in Node.js). Neither is more "secure" than the other in terms of randomness quality. The difference is in format and size: a 21-character NanoID has ~126 bits of entropy (slightly more than UUID v4's 122 bits). Both are safe for generating unguessable identifiers.

Can I use NanoID as a database primary key?

Yes, but with caveats. Random IDs (both UUID v4 and NanoID) cause poor B-tree index performance in traditional databases because inserts are scattered randomly across the index. For high-write databases, consider time-sortable alternatives like UUID v7, ULID, or a custom NanoID with a time prefix. For moderate write volumes, random NanoIDs work fine.

Which is faster, UUID or NanoID?

NanoID is generally faster than UUID generation libraries. In Node.js benchmarks, NanoID generates IDs 2-3x faster than the uuid package. NanoID's implementation is also much smaller (~130 bytes minified vs ~7KB for the uuid package). However, ID generation is rarely a performance bottleneck, so speed should not be the primary selection criterion.

Should I use UUID v4 or UUID v7?

UUID v7 (RFC 9562, finalized in 2024) is generally preferred for new projects. It embeds a Unix timestamp in the first 48 bits, making IDs sortable by creation time. This dramatically improves database index performance compared to random UUID v4. UUID v7 is the modern replacement for UUID v4 in most use cases, especially as database primary keys.

Generate IDs Instantly

Generate UUIDs in bulk with our free UUID Generator. Create up to 25 UUIDs at once with options for uppercase, lowercase, and with or without hyphens.

Related Tools & Guides