Loading...
Loading...
Staff · 50 min
Also asked as: Datadog, Grafana, Google Analytics Realtime, Stripe Dashboard, New Relic.
Read it once, then start the timer and work without scrolling.
Design a realtime analytics dashboard with live-updating charts, where a single view may hold dozens of widgets streaming high-frequency data.
Everything below is a model answer. You will get far more out of this drill by attempting it cold first — set the timer, talk through it out loud, and only then compare.
A 50-minute phase plan you can practise against a clock.
Interactive · Drill rehearsal timer
6:00
Time remaining in Clarify and scope.
What you should establish before drawing a single box.
Architecture, data, interfaces, and optimisations — the RADIO body.
The half of the answer most candidates skip entirely.
Naming how the system breaks, and what the user sees when it does, is the cheapest way to signal production experience. Work through these before the interviewer has to ask.
The interviewer will challenge you. Rehearse the concession, not just the defence.
Interviewer
Why not just poll every second? It is simpler, it works through every proxy, and you avoid a whole class of reconnect bugs.
Model response
For a five-second refresh with a handful of widgets, polling is genuinely the right answer and I would ship it — the reconnect and backpressure machinery I described is real complexity that buys nothing at that rate. Where polling breaks down is the combination of high frequency and many widgets: at one second across twenty widgets you either open twenty request loops, which collides with the browser's per-origin connection limit, or you build a batching endpoint, at which point you have reimplemented multiplexing over a worse transport. You also pay full request overhead to learn that nothing changed. My cut-off is roughly a two-second update interval or more than five or six widgets. Below that I poll and I keep the day of engineering.
Interviewer
You are throwing away React for the chart internals and drawing to canvas imperatively. That is exactly the kind of escape hatch that becomes unmaintainable and untestable.
Model response
The maintainability concern is correct and the escape hatch does have a cost — canvas output is not inspectable by DOM-based tests, and a new engineer cannot reason about it from the component tree. I would contain it rather than avoid it: React owns everything outside the drawing surface, the canvas renderer is a plain class with a data-in, pixels-out interface that is unit tested against fixture data, and visual regression covers the rendered output. The reason I would not keep points in the DOM is not aesthetic. Twenty widgets at two thousand points each is forty thousand nodes re-reconciled per tick, and reconciliation plus layout alone exceeds 16ms before the browser paints anything. If the requirement were five widgets at two hundred points, SVG in React is more maintainable and fast enough, and I would take it.
Interviewer
Server-side downsampling means users are not seeing their real data. If a one-second spike gets averaged away, someone misses an incident, and that is on you.
Model response
That is the most important objection here and averaging is genuinely the wrong default for anomaly detection. Two things address it without shipping raw data to the browser. First, the aggregation must be chosen for the question: max and p99 rollups preserve spikes where mean erases them, and for anything alert-adjacent the default should be max rather than avg. Second, honesty in the UI — the chart labels the served resolution and aggregation, so a user reading a five-minute p99 rollup knows that is what they are reading, and drilling in re-queries at finer resolution over a narrower window. The thing I will not do is send a hundred thousand points to render on six hundred pixels; the browser downsamples it anyway, just invisibly and without letting you choose the aggregation. The real fix for spike detection is server-side alerting on raw data, not a denser chart.
Interviewer
Your whole design assumes one shared connection. That is a single point of failure — when it drops, every widget on the page goes dark at once.
Model response
True, and per-widget connections would give partial degradation. The reason I still take the shared connection is that the failure correlation is largely illusory: twenty separate connections to the same origin through the same network path fail together anyway, and now you have twenty reconnect storms with independent backoff hammering the server at exactly the moment it may be struggling. What I do get from centralization is one place to implement jittered backoff, one Last-Event-ID resume, and one backfill path. Where you would be right is if widgets genuinely spanned different backends with independent failure domains — then I would run one connection per backend, not per widget, so a failure blast radius maps to a real service boundary rather than to a UI element.
Specific signals an interviewer is listening for on this prompt.
Turn one attempt into retained skill.