1 min lesson
Build the problem set from backend primitives
Work through the cases in "Build the problem set from backend primitives", pairing each signal with the move that fits.
Step 1 of 2
Build the problem set from backend primitivesWhat to practice
Skip the abstract graph trivia. Pull problems straight from the Core Services domain so the rehearsal doubles as system-design warm-up. Each of these is implementable in 30 to 45 minutes and maps to something you will own.
Refill at a fixed rate, cap at burst size.
Handle concurrent callers correctly.
Discuss per-key vs global and the clock source.
Exponential backoff capped at a ceiling.
Add full jitter to avoid thundering herd.
Stop on non-retryable errors; bound total attempts.
First call executes, stores result by key.
Repeat call returns the stored result, no re-execution.
Handle the in-flight race and a TTL for eviction.
O(1) get and put with a hashmap plus doubly-linked list.
Evict the least-recently-used on overflow.
Name where you'd put a TTL or size-based variant.
Add one or two stretch problems with distributed-systems texture: a fixed-window vs sliding-window counter, a dead-letter queue with replay or a small consistent-hashing ring. Five problems across a week is enough to get the rust off.
Learn more
Full explanation
A reference token bucket - write yours from scratch first, then compare
class TokenBucket { private tokens: number; private lastRefill: number; constructor( private readonly capacity: number, private readonly refillPerSec: number, ) { this.tokens = capacity; this.lastRefill = Date.now(); } // Returns true if the request is allowed, false if throttled. allow(cost = 1): boolean { const now = Date.now(); const elapsedSec = (now - this.lastRefill) / 1000; this.tokens = Math.min( this.capacity, this.tokens + elapsedSec * this.refillPerSec, ); this.lastRefill = now; if (this.tokens >= cost) { this.tokens -= cost; return true; } return false; } }