Skip to content
About
Main content

Scenarios

Longer problems, like those in senior system design interviews. A strong answer estimates with numbers first, names the mechanism, then recommends a fix and says what it costs.

Try each one before you open the answer.
1A nightly job has 20,000 tasks of 3 minutes each, runs on spot instances that fail at about 0.002 per task-hour, and restarts from scratch on any failure. Is that acceptable? What do you change?Show the answer

Estimate

= 20,000 × 0.05 h × 0.002 = 2. An attempt then succeeds with probability e⁻² ≈ 14%, so the expected number of full attempts is . If one attempt takes an hour, that is over 7 hours of cluster time, and the delivery time is unpredictable.

Decide

Materialize the edges between stages, so a task is the unit of failure: each failure then costs one 3-minute task.

Price

Writing and reading the intermediate data, and a between stages that stops computation overlapping communication. Keep streamed edges for short dashboard queries, where n × T × λ is far below 1.

Check

Tasks must be deterministic and idempotent for retries to be safe.

Read moreThe scale breakDataflow / DAG execution

2An engine team debates rewriting its row-at-a-time interpreted engine as either a vectorized push engine or a query compiler. The workload has scans of a billion rows and also many small dashboard queries. Which do you choose, and what do you measure first?Show the answer

Reason

For a billion rows, the cost of crossing between for every row (tens of cycles each) dominates, so it must be amortized or eliminated. A compiler adds a per query: with 50 ms to compile and 20 ns saved per row, it breaks even at 2.5 million rows. Small dashboard queries fall below that, so a compiler-only engine would be slower on them, and you would need . A vectorized engine with batches of about 1,024 values has no such threshold, and keeps many misses in flight on memory-bound scans.

Measure first

Whether the workload is compute-bound (many expressions) or memory-bound (large ).

Recommend

Push-based and vectorized, with hand-written primitives: easier to profile, debug and port. Add compilation later only for the few computation-heavy pipelines, compiling in the background and switching when ready.

Say also

The performance gap between the two designs is smaller than marketing suggests; engineering cost decides.

Read moreExecution models inside one workerCompiled query executionVectorized execution

3Choose the execution model for a graph job: 100 million vertices, 50 iterations of PageRank-style updates, on 200 machines. Where do you expect the time to go?Show the answer

Choose

Each iteration needs a consistent snapshot of the previous one, so bulk synchronous processing () fits, and it is deterministic.

Estimate

Each costs the slowest computation plus the slowest communication plus barrier . With 200 workers and a of 0.2, the penalty is about ≈ 1.65 per superstep, paid 50 times with no averaging. And computation cannot overlap communication across a barrier.

Mitigate

Balance , and send messages in a pipeline within each superstep. If the algorithm tolerates stale values, asynchronous or bounded-staleness updates help, at the cost of determinism and reproducibility.

Recommend

BSP first; measure the penalty per round; go asynchronous only if the penalty, multiplied fifty times, is unacceptable and convergence is robust to staleness.

Read moreBSP superstepsThe barrier and the maximum

4A team wants to run SQL analytics on a functions-as-a-service platform for a bursty workload: 1,000 workers and a 100 GB shuffle per query, a few queries a day. Evaluate the plan.Show the answer

Requests

1,000 producers × 1,000 consumers = 10⁶ objects of 100 KB. At $5 per million writes, that is $5 per query in writes (), about the same again in reads, plus a latency floor of 10–30 ms per object.

Compute

Functions cost about 3–8× as much as virtual machines per unit of work. But with a few queries a day, a cluster would sit idle most of the time, so paying 5× for the seconds you use beats paying 1× for the hours you do not.

Risks

Requests grow as M × R, so doubling the width quadruples request cost; ; the maximum execution time.

Mitigate

A , fewer and larger partitions (tasks of seconds, not milliseconds), or a fast temporary store for intermediates.

Recommend

Yes for bursty work with narrow shuffles; no for steady heavy load. Re-check the price ratio regularly: it is a pricing decision and has changed before.

Read moreServerless executionTree-structured exchange

5In production, a service has an unbounded in-memory queue between a fast scan thread and a slow join thread, and it crashes with out-of-memory errors under load. How do you fix it, and what do you lose?Show the answer

Diagnose

A push boundary with no way to refuse: the producer decides when data moves, so the consumer cannot say "not yet".

Fix

Bound the queue and make the producer block, or use credits as Flink does. Size the buffer by : depth ≈ arrival rate × the consumer's latency, enough to keep the consumer busy through the producer's pauses and no more. Too small and the pipeline serializes; too large and you spend memory hiding variance.

What you lose

The producer now stalls, so is limited by the slow stage, as it always really was, and LIMIT or cancellation needs a stop signal.

Alternative

Make the boundary pull-based: refusal comes free, at the cost of a call per unit, which batching can pay back.

Read morePush-based executionThree idlenesses

6A 100-minute job barely speeds up on twice as many machines. Diagnose it.Show the answer

Compute the ceiling

From per-task counters, find f, the largest partition's share of the work. If it is 5%, the speedup is capped at 1 / f = 20, whatever the cluster size.

Classify

Plot task duration against input bytes to tell from stragglers and imbalance.

If it is skew

Split the unit: salt known hot keys; split partitions adaptively if shuffle files can be read by range; or separate heavy hitters, if a sketch can find them.

Do not start with

: a copy of a big task is just as big.

Also check

The number of stages: fix how much can overlap.

Trade-offs

multiplies the other side of a join by the number of salts; adaptive splitting needs sorted, indexed shuffle files.

Read moreData parallelismClassify the long tailSaltingAdaptive partition splitting

7Design the shuffle for a 10 TB join on object storage, with 10,000 tasks on each side.Show the answer

Estimate

Each block would be 10 TB ÷ 10⁸ = 100 KB, far below 's efficient floor of 2–8 MB. Requests at 100 KB per object cost about , about $500 for 10 TB. The is ≈ 2,236, so 10,000 is well above it.

Design

Reduce the bytes first (projection, pre-combining, broadcasting any small side), reduce the width towards 2,000, use sort-based shuffle, and put a service with local disks in front of object storage, so consumers make large reads.

Accept

An extra hop and a shared stateful service; keep the unmerged blocks as a fallback.

Read moreThe two numbers that govern everything herePush-based and remote shuffleObject storage as the shuffle medium

8Autoscaling added 20 machines to a running job, and it did not finish any sooner. Why?Show the answer

Estimate

Scaling out mid-query pays only if . With 60 core-seconds of work left, going from 10 workers to 20 saves 3 s and costs 30 s of startup.

Also

The job may already be at its task-count ceiling (total work ÷ the smallest sensible task).

Design

Elasticity belongs between queries, or early in long ones. For elasticity inside a query, over-partition and detect the need early.

Read moreElastic parallelism

9After the network was upgraded from 10 to 100 Gbps, shuffle-heavy jobs got slower, and occasionally totals are wrong after task retries. Explain both.Show the answer

Slower

Shuffle compression was turned on when it paid, when codec throughput exceeded . A 1 GB/s codec with ratio 2 would now need 25 GB/s to win on a 12.5 GB/s link. Turn it off, keeping it for slow cross-zone links.

Wrong totals

A non-deterministic or UDF, for example a random salt, sends rows to different partitions on a retry. Make it deterministic (a hash of the task ID and row index) before enabling retries or speculation.

Also check

That output from failed attempts is never read: only one attempt's output should be committed for each task.

Read moreShuffle compressionThe partition function must be deterministic