Data & storage
Distributed IDs
Mint globally unique, roughly time-sortable ids from independent nodes — without ever asking a central sequence for "the next number."
Auto-increment doesn't scale across nodes
A single incrementing primary key needs one place that knows "the last value" — that's a coordination bottleneck and a single point of failure. Split it across shards with no coordinator and each node's own counter will mint the SAME id.
-- one sequence, one source of truth
CREATE TABLE orders (
id SERIAL PRIMARY KEY -- next id? ask the DB, every insert waits
);
// shard A and shard B, no coordinator:
shardA.nextId() // -> 5
shardB.nextId() // -> 5 ✗ COLLISION
Coordination-free id schemes
Each node mints its own ids from local state — no round-trip to a shared counter.
// UUIDv4 — 122 random bits
"e2c1-4a9b-...-91fd" // unique, unordered
// Snowflake — 64 bits, no coordinator
id = (time << 22)
| (node << 12)
| (seq); // seq resets each tick
// ULID — timestamp + randomness
"01ARZ3-NDEKTSV4RRFFQ69G5FAV"
Result: Snowflake ids are globally unique, roughly time-sortable, and compact — UUIDv4 is simplest but random and index-unfriendly — ULID mixes both.
Two nodes, one shared clock, zero collisions
Both nodes only share a logical clock. Tick it, mint from either node — every id stays unique with no coordinator involved.
Unique ids, no central sequence
- Coordination-free: every node mints ids from its own state — no shared counter to bottleneck on or fail over.
- Snowflake = sortable + compact — the time prefix gives good index locality (B-tree friendly), unlike random ids.
- UUIDv4 = simplest to adopt but fully random — no ordering, worse index locality.
- Watch clock skew: if a node's clock jumps backward, its "time-sortable" ids can briefly go out of order — sync clocks (NTP) and monitor drift.
- Once ids scale across nodes, the next question is which node owns which data — see sharding.