Design a distributed unique ID generator (Snowflake)

A single database counter does not scale across servers. Learn UUIDs, Snowflake-style 64-bit IDs and the clock traps.

A numbered ticket being stamped by several machines

Goal: create IDs that are unique across many servers, generated fast without coordination, and ideally sortable by time.

Why not a database auto-increment

  • A single counter is a bottleneck and a single point of failure.
  • With sharded databases, each shard would generate overlapping numbers.
  • Sequential IDs expose how many records you have and are easy to guess.

Option 1: UUID

A 128-bit random identifier (UUIDv4). Any server can create one with a negligible chance of collision.

  • Pros: no coordination at all.
  • Cons: 16 bytes, not sortable by time. Random keys hurt database index locality, so inserts into a B-tree are slower and the index is bigger.

Option 2: time-ordered IDs (UUIDv7, ULID)

They put a timestamp at the start and random bits after it. IDs sort roughly by creation time, which keeps indexes friendly, and there is still no coordination.

Option 3: Snowflake-style 64-bit ID

Popularised by Twitter. A 64-bit integer built from parts:

Part Bits Meaning
Sign 1 always 0
Timestamp 41 milliseconds since a custom start date (about 69 years)
Machine ID 10 which worker made it (up to 1,024)
Sequence 12 counter within the same millisecond (4,096 per ms per machine)

Each machine can make about 4 million IDs a second. IDs are unique (different machine bits), sortable by time, and fit in a normal 64-bit integer column.

Problems to handle

  • Machine ID assignment: give each worker a unique ID, from a coordination service (ZooKeeper/etcd) or configuration.
  • Clock going backwards: NTP corrections can move time back and create duplicates. Detect it and wait, or refuse to generate until the clock catches up.
  • Sequence overflow: if more than 4,096 IDs are needed in one millisecond, wait for the next millisecond.
  • Clock skew across machines only affects exact ordering, not uniqueness.

Other approach: ticket servers

A dedicated service hands out blocks of numbers to app servers, which then assign them locally. Simple, but the service must be highly available.

Which to choose

Need Choice
Simplest, no coordination UUIDv4 (or UUIDv7 for better indexes)
Compact 64-bit, sortable Snowflake-style
Strictly ordered, single database Sequence

Takeaway: use a time-ordered ID. UUIDv7 for simplicity, or Snowflake when you need compact 64-bit IDs, and guard against clocks that move backwards.


System Design series, Part 4 (designing the infrastructure): 1 of 4.

Keep reading