Once data lives on many machines, a database's auto-increment column can no longer hand out IDs: each shard would produce its own 1, 2, 3. Distributed systems need IDs that are unique without coordination on every insert, fit in an index nicely, and often sort roughly by time. This page compares the standard options and when to use each.
Like a railway PNR: the number itself encodes when and where it was issued, so every counter in the country can issue tickets without calling a central office, and no two tickets ever get the same number.
| Approach | Size | Sortable by time | Coordination | Notes |
|---|---|---|---|---|
| DB auto-increment | 64-bit | yes | single DB | simple; bottleneck and SPOF at scale |
| Multi-master step (odd/even) | 64-bit | roughly | fixed N servers | server k issues k, k+N, k+2N; hard to add servers |
| Ticket server / ID blocks | 64-bit | roughly | one fetch per block | apps lease ranges of 1,000 ids; fast; central dependency |
| UUID v4 | 128-bit | no | none | random; poor B-tree locality; long |
| UUID v7 / ULID | 128-bit | yes | none | timestamp prefix + randomness; index-friendly |
| Snowflake | 64-bit | yes | worker id assignment | time + machine + sequence; very fast |
64-bit id (Twitter Snowflake layout)
| 1 sign | 41 bits: ms since custom epoch | 10 bits: worker id | 12 bits: sequence |
~69 years 1,024 workers 4,096 ids/ms/worker
def next_id():
now = current_millis()
if now == last_ms:
seq = (seq + 1) & 0xFFF
if seq == 0: # 4,096 used this ms -> wait for next ms
now = wait_until_next_ms(last_ms)
else:
seq = 0
if now < last_ms: raise ClockMovedBackwards # or wait / refuse
last_ms = now
return ((now - EPOCH) << 22) | (worker_id << 12) | seq
IDs from one worker are strictly increasing; across workers they are roughly time-ordered (k-sorted). The worker id must be unique: assign it from configuration, or lease it from ZooKeeper/etcd at startup.
Coordination-free schemes (UUID) are simplest but bigger and less index-friendly. Snowflake is compact and ordered but needs worker id management and sane clocks. Central counters are simple and dense but add a dependency. Pick by size, ordering and operational tolerance.