Free preview

Approach 3: The Range Handler

Why this matters: this is the first design that satisfies every requirement, and the idea behind it — amortize coordination by batching it — appears everywhere once you recognize it.

Key takeaway

A central microservice (the range handler) manages ID ranges. Application servers claim a range, then assign IDs from it locally — so coordination happens once per hundred thousand IDs instead of once per ID.

How it works

The flow:

  1. Application servers request a range from the central handler — for example 1–1,000,000 or 1,000,001–2,000,000.
  2. The server stores the range start and end points locally.
  3. When an ID is needed, the server assigns the current value and increments it locally.
  4. When the range is exhausted, the server requests a new range.

Example: Server 1 claims 300,001–400,000. It assigns 300,001 to the first request, then 300,002, and so on until 400,000 is assigned. Then it queries the central handler for the next available range.

This prevents duplicates and allows concurrent responses. A load balancer distributes requests across servers to manage load.

Surviving failure

The range handler tracks range status — available versus taken — in replicated storage. A failover server ensures availability if the main handler fails, recovering state from the storage checkpoint.

Note that the handler being briefly down is not an outage: every application server is still serving IDs from the range it already holds. The system only stalls if a server exhausts its range while the handler is unavailable — which is why range size is a real tuning decision.

Pros and cons

Detail
ProsScalable, available, and guarantees unique IDs. It also satisfies the requirement for 64-bit numeric IDs
ConsIf an application server fails, its unassigned range is lost, creating gaps in the ID sequence. Mitigate by allocating smaller ranges — though they must be large enough to minimize network requests to the central handler

Scorecard

UniqueScalableAvailable64-bit numeric ID
Using UUID
Using database servers
Using a range handler

All four requirements satisfied. The solution generates unique 64-bit numeric IDs suitable for primary keys.

However, these IDs do not guarantee time-based ordering — which is where the second half of this chapter begins.

Key takeaway

Batching coordination turns a per-ID dependency into a per-range one, which is what makes the range handler both available and genuinely unique. The remaining gap is ordering: nothing about a range tells you when an ID was issued.

Interview signal by level

LevelWhat a strong answer sounds like
L4"A service hands out ID ranges to each server."
L5Explains why it works: "each server owns a block, so it assigns locally with no coordination until the block runs out."
Staff+Generalizes and tunes it: "it amortizes coordination — once per 100k IDs instead of per ID, the same pattern as leases or connection pools. Range size trades handler load against IDs lost on server failure, and gaps are fine unless something downstream assumes contiguity. For multi-DC I'd partition the range space per DC so a partition can't cause a collision."

Next: why unique isn't enough.

Enjoying the preview?

Create a free account to unlock the rest of this course, the in-browser judge, and live AI mock interviews.

Sign up free to continue