UUID vs UUIDv7 vs Snowflake IDs: Choosing a Primary Key

Why developers are moving from auto-increment integers to UUIDs, where UUIDv4 falls short, and how UUIDv7 and Snowflake IDs fix the indexing and ordering problems.

1. Why Developers Are Switching to UUIDs

Developers increasingly prefer UUIDs over auto-increment integers because:

✅ 1.1. Decentralized ID Generation

  • No need for database-side sequencing.
  • Multiple services/machines can create IDs without coordination.

✅ 1.2. Perfect for Distributed Architectures

  • Works well with microservices, event-driven systems, and multi-region apps.
  • Avoids "ID collisions" across services.

✅ 1.3. Security Through Obscurity

  • Sequential numeric IDs expose the scale of your system.
  • UUIDs prevent ID enumeration attacks like:
    • /users/1, /users/2, etc.

✅ 1.4. Easier Migration & Sharding

  • UUIDs remain unique across shards.
  • Smooth migrations across environments (dev/stage/prod).

✅ 1.5. Better for Client-Side Generated Data

  • Offline-first apps can generate IDs even without a backend.

2. Drawbacks of Traditional UUIDs (UUIDv4)

❌ 2.1. Poor Index Locality

  • UUIDv4 is completely random.
  • Inserts scatter across the B-Tree index.
  • Causes:
    • Page splits
    • Fragmentation
    • Slower writes
    • Larger index size

❌ 2.2. Bad for Ordering

  • No time component → cannot sort by creation time.
  • Requires separate createdAt column to track chronology.

❌ 2.3. Larger Storage Cost

  • 16 bytes vs 4 bytes (int) or 8 bytes (bigint).
  • Impacts:
    • Indexes
    • Joins
    • Foreign key storage

❌ 2.4. Harder to Debug

  • Hard to visually understand the sequence of operations or logs.

3. Modern Solutions to UUID Problems

UUIDv7 = timestamp + randomness.

✅ Benefits
  • Sortable (monotonic increasing) → great for indexing.
  • Better insertion locality (fixes UUIDv4’s major pain).
  • Has microsecond timestamps.
  • Globally unique without coordination.
  • Ideal for database usage.
📌 Why it indexes better?
  • Because the timestamp prefix ensures new IDs are near the end of the index → fewer page splits.
Example (Node.js, TypeScript)
TS
import { uuidv7 } from 'uuidv7';
const id = uuidv7();

3.2 Snowflake IDs (Twitter Snowflake, KSUID, ULID, etc.)

Structure (typically)
TEXT
Timestamp | Machine ID | Sequence
✅ Advantages
  • Lexicographically sortable.
  • Very fast to generate.
  • Smaller than UUID (64-bit or 128-bit).
  • Good for:
    • High throughput systems
    • Distributed services
    • Ordered event logs
❌ Disadvantages
  • Requires configuration:
    • Machine ID / worker ID
  • Must avoid:
    • Clock drift
    • Duplicate worker IDs
  • Some implementations are not globally coordinated.
ID Type Sortable Randomness Fits in bigint Notes
UUIDv4 ❌ No High ❌ No Random but bad for DB
UUIDv7 ✅ Yes Medium ❌ No Best modern/default choice
ULID ✅ Yes Medium ❌ No URL-safe, readable
KSUID ✅ Yes Medium ❌ No Great for event logs
Snowflake ✅ Yes Low ✅ Yes Perfect for bigint PKs

4. Should You Use UUID as Primary Key?

Best cases:

  • Distributed systems
  • Multi-region applications
  • Event logs
  • Offline clients
  • Microservices
  • Large teams where different services create data

When NOT to use UUID:

  • Very high write load tables where index bloat matters.
  • When you need compact storage (IoT, embedded systems).
  • When your DB performance matters more than independence.

👍 Use UUIDv7 for:

  • Most modern applications
  • PostgreSQL / MySQL / MongoDB
  • Systems needing sortable, index-friendly IDs
  • Minimal configuration

👍 Use Snowflake IDs when:

  • You want bigint-compatible IDs (required by some ORMs).
  • You need extremely high throughput (thousands-millions IDs/sec).
  • You want sortable IDs but smaller than UUID.

6. Summary

Option Best For Pros Cons
UUIDv4 Legacy, simple setups Random, unique Bad indexing, non-sortable
UUIDv7 Most apps today Sortable, index-friendly 128-bit storage cost
Snowflake ID Bigint PKs, high-perf systems Compact, sortable, fast Needs worker IDs, clock sync
ULID/KSUID Event systems, logs Readable, sortable Not as standardized

7. Final Recommendation

➡ For general application development (Node.js + PostgreSQL), use UUIDv7.
➡ For extremely high throughput systems with bigint constraints, use Snowflake IDs.

Adesh Tamrakar
SOFTWARE ENGINEER · VAULT

Notes, insights and random discoveries from a working engineer's vault - written for future me, published for you.