Every order requires a globally unique, time-sortable Order ID. Multiple services across regions generate IDs simultaneously. How would you design this?
How I frame it
Clarify scale (orders/sec), multi-region requirement, and whether IDs are customer-facing or internal. Sortable IDs help sharding, analytics watermarks, and support "show orders after this time" without a global sequence bottleneck.
Requirements
- Globally unique — no collision across regions/services.
- Time-sortable — support queries "orders after T" without central sequence.
- High throughput — no single DB bottleneck per ID.
Snowflake-style 64-bit ID
Bits: timestamp_ms | datacenter_id (5) | machine_id (5) | sequence (12). ~4096 IDs/ms per machine. Sortable by time; unique if machine IDs assigned via config service / K8s StatefulSet.
- Clock backward NTP jump: Wait until caught up or use last timestamp.
- Sequence overflow in 1ms: Block until next millisecond.
- Alternatives: UUIDv7, ULID — standard libraries, good enough for most e-commerce.
EU order service + US order service Each has unique (dc_id, machine_id) No coordination per ID generation IDs sort ≈ creation time for sharding
When not Snowflake
DB sequence per shard adds coordination latency. Human-readable order numbers may use separate display id + internal snowflake.
Walkthrough
US order service (machine 12) and EU order service (machine 87) both create orders at 14:00:00.001. Snowflake IDs share timestamp prefix — sortable in global order feed. No central DB sequence bottleneck. Support queries orders WHERE id > last_id for incremental sync to warehouse.
Weak answer
"Auto-increment in MySQL." Single-writer bottleneck; not multi-region friendly. "UUID v4" — unique but not time-sortable; bad for range queries and sharding hot spots.
Follow-up questions
Machine id collision after autoscale?
Lease machine_id from ZooKeeper/etcd on pod start; release on shutdown. Or embed pod UID in id scheme.
Privacy — ID leaks order volume?
Public-facing opaque token separate from internal sortable id.