Unique ID Generator in Distributed Systems (Snowflake, UUID)

8 min read

Reading Progress0%
System Design Index
Start Here
Tier 1 -- Building Blocks
Tier 2 -- Core Systems
URL Shortener — System Design InterviewFree
Pastebin — System Design InterviewFree
News Feed System — System Design InterviewFree
Chat System (WhatsApp/Messenger) — System Design InterviewFree
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative
System Design Index
Start Here
Tier 1 -- Building Blocks
Tier 2 -- Core Systems
URL Shortener — System Design InterviewFree
Pastebin — System Design InterviewFree
News Feed System — System Design InterviewFree
Chat System (WhatsApp/Messenger) — System Design InterviewFree
Tier 3 -- Location & Real-Time
Tier 4 -- Infrastructure & Data
Tier 5 -- Finance & Commerce
Tier 6 -- Advanced & Collaborative

Unique ID Generator in Distributed Systems (Snowflake, UUID)

Tier 1 — Building Block


1. What Is It?

A unique produces globally unique identifiers for records in a distributed system where multiple servers create records simultaneously. Unlike a single-machine database with an AUTO_INCREMENT , distributed systems cannot rely on a central counter — doing so creates a bottleneck and .

The problem: if ten app servers are simultaneously inserting rows into a sharded database, each server needs a unique ID for its row that will not collide with IDs generated by the other nine servers. The ID must be unique across all shards, ideally sortable by time (so you can query "records created after X"), and generated without cross-server coordination.

Without a good solution, you either have a central database counter (bottleneck), random UUIDs (non-sortable, large), or per-node counters (collision risk). Each has serious drawbacks at scale.


QUICK CHECK

A team is building a sharded database where ten app servers insert records simultaneously. They consider using a single centralized counter service to generate IDs so every server gets a globally unique, incrementing value. What is the primary drawback of this approach?

Choose one answer

2. How It Works

Twitter Snowflake (the canonical approach)

Snowflake IDs are 64-bit integers composed of three fields:

 63 62       22 21   12 11       0
 |--|---------|------|----------|
 sign timestamp worker  sequence
  1    41 bits  10 bits  12 bits
FieldBitsRangePurpose
Timestamp41~69 years from epochMilliseconds since custom epoch (e.g., Nov 4, 2010 for Twitter). Provides time-sortability.
Worker ID100–1023Identifies the machine (datacenter ID 5 bits + machine ID 5 bits in Twitter's original). Prevents collisions across nodes.
Sequence120–4095Per-millisecond counter on each worker. Rolls over to 0 each millisecond. Prevents collisions from the same worker in the same millisecond.

Max per node: 4,096 IDs/millisecond = 4.096 million IDs/second per worker. With 1,024 workers: ~4 billion IDs/second globally.

Generation pseudocode:

function next_id(worker_id):
    timestamp = current_time_ms() - EPOCH
    if timestamp == last_timestamp:
        sequence = (sequence + 1) & 0xFFF  # 12-bit mask
        if sequence == 0:
            wait until next millisecond  # Overflow: all 4096 IDs used this ms
    else:
        sequence = 0
    last_timestamp = timestamp
    return (timestamp << 22) | (worker_id << 12) | sequence

UUID v4 (Random)

128-bit randomly generated identifier. Example: 550e8400-e29b-41d4-a716-446655440000

  • Pros: Zero coordination needed; works completely offline; no centralized service
  • Cons: 128-bit (vs. 64-bit Snowflake) — larger indexes, worse B-tree performance (B-trees are the sorted tree structures databases use for indexes); not sortable by time; random distribution causes B-tree page splits on inserts (index fragmentation)

UUID v7 (Time-Ordered, RFC 9562)

A newer UUID variant: first 48 bits are millisecond Unix timestamp, remaining bits are random. Gives time-ordering while remaining decentralized.

  • Pros: Time-sortable like Snowflake; no coordination; 128-bit compatibility with UUID infrastructure
  • Cons: Still 128-bit (larger than 64-bit Snowflake); slightly less compact

Database Auto-Increment (Not Distributed)

AUTO_INCREMENT in MySQL / SERIAL in PostgreSQL — the simplest approach for single-database systems.

  • Pros: Dead simple; guaranteed sequential; perfect B-tree locality
  • Cons: ; bottleneck for high write ; doesn't work across multiple shards

3. Variants & Comparisons

ApproachSizeSortable?CoordinationMax RateBest For
DB Auto-Increment64-bit intSequentialCentralized DBLimited by DB writesSingle-node systems
UUID v4128-bitNo (random)None (offline)UnlimitedSimple uniqueness without time ordering; legacy UUID infra
UUID v7128-bitYes (time-prefixed)None (offline)UnlimitedTime-ordered IDs with UUID compatibility
Snowflake64-bitYes (~ms precision)Worker ID assignment only4M/sec/workerHigh-throughput distributed systems needing sortable IDs
ULID128-bitYes (ms-sortable)NoneUnlimitedURL-safe, human-readable sortable IDs
Sonyflake64-bitYesWorker ID assignment~25,600/sec/worker8-bit sequence per 10ms tick, 16-bit machine ID
Ticket Server (Flickr)64-bit intSequential per tableCentralized ticket DB~5K/secLegacy; simple centralized counter service

ULID (Universally Unique Lexicographically Sortable Identifier)

01ARZ3NDEKTSV4RRFFQ69G5FAV
|----------|--------------|
 timestamp    randomness
  48 bits      80 bits
  10 chars     16 chars
  • 128-bit, Crockford Base32 encoded
  • Monotonically sortable within the same millisecond
  • No central coordination

QUICK CHECK

Your team needs to generate IDs for user activity events in a high-traffic distributed system. The IDs must be sortable by time, URL-safe, and require no central coordination service. Which approach best fits these requirements?

Choose one answer

4. When to Use It (and When NOT To)

When to Use Each Approach:

  • Snowflake-style: You need 64-bit integer IDs (small index size, fast comparisons), time-ordered inserts (good B-tree locality), and can assign worker IDs at startup. Ideal for: social media posts, messages, events, orders.
  • UUID v7: You need IDs compatible with UUID infrastructure (128-bit), time-ordered, but want to avoid central coordination. Ideal for: microservices where each service generates its own IDs without central ID service.
  • UUID v4: You need zero-infrastructure uniqueness. Acceptable when: the table is small, random access patterns make B-tree page splits acceptable, or you're in a system that already uses UUID format.
  • DB auto-increment: Single-database system, sequential IDs required, no needed.

Decision triggers:

  • "If inserting > 10K rows/sec into a sharded database → Snowflake or UUID v7 (avoid random UUID — index fragmentation kills write )"
  • "If you need IDs sortable by creation time (for pagination, feeds) → Snowflake or UUID v7"
  • "If you have no central coordination and need maximum simplicity → UUID v4 or v7"

Anti-patterns:

  • Random UUIDs as B-tree primary keys at scale: Every insert goes to a random page in the index. At tens of millions of rows, >90% of inserts cause page faults (non-sequential I/O). Use Snowflake or UUID v7 for write-heavy tables.
  • Using wall clock time without monotonic check: If the server clock moves backward (NTP adjustment), Snowflake can generate duplicate IDs for the same worker. Fix: detect clock drift and wait or throw an error.
  • Exposing Snowflake IDs in APIs: Snowflake IDs embed your worker topology and timestamp — leaks information. Consider obfuscating (e.g., XOR with a secret) if the ID is exposed publicly.
  • Single service: The ID generation service itself becomes a SPOF. Deploy one per app server (embedded library), not as a centralized service.

QUICK CHECK

A backend team is building a write-heavy social feed service that inserts over 50,000 rows per second across a sharded database. They currently use UUID v4 as the primary key. They notice write throughput degrading as the table grows past 100 million rows. What is the most likely root cause, and which ID strategy would best address it?

Choose one answer

5. Real-World Usage

Twitter Snowflake: Twitter open-sourced the original Snowflake in 2010. Tweet IDs are Snowflake IDs — they are 64-bit integers, sortable by time, and generated at each tweet creation service instance without coordination (worker IDs are assigned at startup via ZooKeeper, a distributed coordination service). This is why tweet IDs increase monotonically over time: tweet 1234567890 was created before tweet 2345678901. Generating ~6K tweets/sec at peak required a system that could never bottleneck on ID generation.

Discord Snowflakes: Discord uses a Snowflake variant for message IDs, user IDs, channel IDs, and server IDs. Discord's API exposes a since_id pagination pattern — "give me all messages with ID > X" — which only works because Snowflake IDs are time-ordered. Discord's worker ID encodes epoch differently (Discord epoch = 2015-01-01) but the structure is otherwise identical to Twitter's.

Instagram (64-bit IDs with PL/pgSQL): Instagram used a different approach: a PostgreSQL stored procedure (id_generator) that uses a combination of timestamp + shard ID + sequence number, generating 64-bit IDs within the database using PL/pgSQL. This avoids a separate ID service entirely; each PostgreSQL shard generates IDs for its own data. The approach produces ~1000 IDs/sec per DB connection — sufficient for their write rate.


QUICK CHECK

Discord's API supports a since_id pagination pattern, where clients request 'all messages with ID greater than X'. Which property of Discord's Snowflake-based message IDs makes this pagination pattern reliable?

Choose one answer

6. Interview Cheat Sheet

Key sentences to demonstrate depth:

  1. "Snowflake IDs are 64-bit integers: 41-bit millisecond timestamp + 10-bit worker ID + 12-bit sequence. This gives 4,096 IDs per millisecond per worker with no cross-node coordination — just assign unique worker IDs at startup."
  2. "The key advantage of time-ordered IDs (Snowflake, UUID v7) over random UUIDs is locality: sequential inserts fill pages from left to right without splits, maintaining near-100% page utilization and avoiding ."
  3. "The Snowflake clock drift problem: if a server's clock moves backward, the same worker might generate the same sequence for the same apparent millisecond. Mitigation: detect clock drift, refuse to generate IDs until clock catches up."
  4. "For an interview question about ID generation, I'd default to Snowflake-style: embedded in each app server, ZooKeeper or a config service assigns worker IDs at startup, no centralized ID service needed."
  5. "UUID v4 is fine for low-write-rate tables or when you need UUID format compatibility. At high write rates (>10K rows/sec) on a B-tree , random UUIDs cause severe index fragmentation — switch to Snowflake or UUID v7."

Common follow-up questions:

QuestionConcise Answer
"What happens if the Snowflake sequence overflows (4096 in one ms)?"Generator waits until the next millisecond before issuing more IDs. At 4,096 IDs/ms = 4M IDs/sec per node, this is rarely hit in practice.
"How do you assign worker IDs?"Option 1: ZooKeeper ephemeral nodes — each service instance claims a unique node ID at startup, releases on shutdown. Option 2: Kubernetes pod IP last 10 bits. Option 3: Central config service that assigns and tracks worker IDs.
"Can two workers have the same worker ID?"That would cause collisions. Worker ID assignment must be strictly exclusive. ZooKeeper sequential ephemeral nodes are the canonical solution.
"What's the maximum timestamp range for 41-bit timestamp?"2412^{41} milliseconds = ~69.7 years. With a 2010 epoch, overflow occurs around 2079.
"Why 64-bit and not 128-bit?"64-bit fits in a native integer type in most languages — cheaper comparisons, smaller indexes, fits in CPU registers. Database row size matters at billions of rows.

Connections to other building blocks:

  • & : In a sharded database, IDs must be globally unique across shards. Snowflake IDs include a worker ID (often includes shard ID) to guarantee uniqueness.
  • Distributed Locking: Assigning Snowflake worker IDs at startup requires a or coordination service (ZooKeeper, etcd) to prevent two nodes from claiming the same worker ID.
  • Message Queues: message offsets and Cassandra's TIMEUUID serve similar purposes — time-ordered unique identifiers for events in a distributed log.
  • CAP Theorem: Centralized ID services (Ticket Server) are CP — if the service is down, ID generation stops. Snowflake (embedded per node) is AP — each node generates IDs independently, tolerating network partitions.
Glossary History

Click dotted jargon to save explanations here.

Glossary History

Click dotted jargon to save explanations here.