Business Intelligence, Reporting, and Dashboards Questions
The reporting and presentation layer of analytics: semantic/metrics layers, report development and automation, self-service BI, and the architecture that feeds dashboards and reports. Covers dashboard and visualization design (tool selection across Tableau/Power BI/Looker-style platforms, drill-downs, information architecture, communicating metrics visually), refresh strategies, and query performance for interactive reporting workloads. Spans both the engineering behind the reporting layer and the design of the dashboards that consume it.
Design the ongoing incident-response PROCESS for broken reports and stale data at your company, not the response to any one incident: what triggers it, who gets paged, what a runbook actually needs to contain to be useful at 2am, and what you'd review after the incident closes.
Sample Answer
Direct answer
An ongoing incident-response process for broken reports and stale data, as opposed to responding to any single incident, needs a clear trigger for when it activates, a defined on-call rotation and escalation path, runbooks specific enough to actually be useful at 2 AM by someone half-asleep, and a real post-incident review that produces concrete follow-up actions rather than just a closed ticket.
Structured elaboration
Triggers: what specifically counts as an incident worth activating this process versus a routine issue handled through normal channels, typically tied to the severity tiers established by SLO (service-level objective) definitions (a tier-1 report breaching its freshness or correctness SLO triggers the formal process; a low-traffic internal report doing the same might not).
On-call and paging: who gets paged, based on the report's tier and the time of day, with a clear primary/secondary escalation path if the first responder doesn't acknowledge within a defined window.
What a runbook needs to actually be useful under pressure: specific, step-by-step diagnostic actions for the most common failure categories (a job failure, a stale refresh, a data-quality anomaly), not a generic "investigate and fix" instruction; a runbook written by someone calm and rested needs to anticipate that the person USING it might be neither, so it should minimize the judgment calls required and maximize concrete, checkable steps (which specific logs to check first, which dashboard shows job status, who the specific escalation contact is for each failure category).
Communication templates: pre-drafted or at least pre-structured messages for common scenarios (a stale-data notice, a wrong-number correction notice) so the responder isn't composing a careful stakeholder message from scratch while also trying to diagnose the technical problem.
Post-incident review: after the incident is resolved, a structured review of what happened, why, how it was caught (or why it wasn't caught sooner), and what specific, assigned follow-up actions would prevent a recurrence or catch it faster next time, tracked to completion rather than just discussed once and forgotten.
Worked example
A company defines its incident-response process with three severity tiers matching its report SLO tiers: tier-1 (executive/customer-facing) failures page on-call within 5 minutes and require an update to stakeholders within 30 minutes; tier-2 (internal, moderate-traffic) failures page during business hours only, with a same-day resolution target; tier-3 (low-traffic internal) failures go to a queue reviewed each morning, no paging. The runbook for the most common failure category, "scheduled refresh failed," gives explicit steps: check the specific orchestrator dashboard URL for the failed job's error message, cross-reference against a documented list of the five most common failure causes and their standard fixes, and if none match, escalate to a named secondary contact rather than continuing to investigate solo past a defined time limit. After a real tier-1 incident (a failed refresh that took 40 minutes to resolve instead of the target 30), the post-incident review identifies that the on-call engineer spent 15 of those 40 minutes trying to figure out which upstream team to contact, a gap the runbook didn't cover; the assigned follow-up action, adding an explicit upstream-team contact list to the runbook, is tracked and confirmed complete within a week, not just noted and forgotten.
Trade-offs and pitfalls
A runbook that tries to cover every conceivable failure scenario in exhaustive detail becomes too long to actually use quickly during a real incident, so the discipline is prioritizing the MOST COMMON failure categories with real depth and accepting that a genuinely novel failure will require judgment and escalation rather than trying to anticipate everything. Post-incident reviews are also easy to let become a box-checking exercise (a meeting happens, notes are taken, nothing changes) unless follow-up actions are explicitly assigned with an owner and a deadline and actually tracked to completion, which is often the difference between an incident-response process that genuinely improves over time and one that repeats the same failure patterns indefinitely.
A scheduled dashboard or report didn't refresh overnight and stakeholders are looking at yesterday's numbers this morning, or a critical KPI tile has suddenly gone blank or null. Walk through how you would investigate, contain, and communicate about the incident in real time, and what you would check afterward to prevent a repeat.
Sample Answer
Direct answer
When a scheduled report fails to refresh overnight, or a critical KPI (key performance indicator) tile suddenly shows null, the response has three phases that need to happen roughly in order: figure out what actually broke and how badly, communicate honestly and promptly to whoever's affected, and only then dig into the deeper root cause, because stakeholders waiting on stale or missing data need a status update long before you have a complete diagnosis.
Structured elaboration
Immediate investigation: check the pipeline's job logs first, did the scheduled job actually run, did it fail with an error, or did it succeed but produce bad output. This single check usually narrows the problem space enormously (a clean failure with an error message is a very different investigation than a job that reported success but produced wrong data).
Containment: if there's a way to prevent the bad state from getting worse or spreading (pausing a downstream job that depends on this report's output, or reverting to the last known-good snapshot so at least stale-but-correct data is showing instead of broken data), do that before diving into root cause.
Communication in real time: tell affected stakeholders what's known so far, roughly how long a fix might take if that's estimable, and when they'll hear an update next, even if the update is "still investigating." Silence during an incident erodes trust faster than an honest "we don't know yet, but we're on it."
Root cause identification: once the immediate situation is stable, dig into WHY it happened, an upstream data source that didn't land on time, a schema change nobody flagged, a resource limit hit during a particularly large run.
Prevention for next time: what instrumentation or runbook would have made this faster to catch or diagnose. A recurring theme across incidents like this is that better MONITORING (catching the failure within minutes instead of stakeholders noticing hours later) is often a higher-leverage fix than trying to prevent every possible failure cause.
Worked example
A scheduled daily dashboard shows yesterday's numbers again this morning; stakeholders notice before the on-call engineer does. Investigation: the job logs show the nightly refresh job actually failed at 2 AM with a connection timeout to an upstream source, not a silent data problem, a relatively good outcome since a clean failure is easier to diagnose than a silent bad-data scenario. Containment: since the dashboard is still showing yesterday's (stale but not wrong) data rather than something broken, no additional containment is needed beyond confirming this. Communication: an update goes out within 15 minutes of the issue being confirmed, explaining that the refresh failed due to an upstream connectivity issue, that data currently shown is yesterday's (clearly stale, not incorrect), and that an update will follow once the refresh completes. Root cause: the upstream source had an unannounced maintenance window that the pipeline's timeout settings weren't configured to tolerate. The fix ships (adjusting timeout and retry behavior), and separately, an alert is added that pages on-call the moment a scheduled job fails, rather than waiting for a stakeholder to notice stale data hours later, directly closing the gap between "it broke" and "someone knew."
Trade-offs and pitfalls
The most common mistake under incident pressure is going silent while deep in root-cause investigation, technically working the problem the whole time, but from the stakeholder's perspective indistinguishable from nobody addressing it at all; a quick, honest "still investigating, next update in 30 minutes" costs almost nothing and preserves trust even when the underlying fix takes a while. The other real trap is treating every incident as needing the SAME depth of root-cause investigation regardless of severity; a low-stakes internal report failing overnight probably doesn't need the same forensic rigor as a customer-facing or executive-facing failure, and spending equal effort on both means the high-stakes incident gets less attention than it deserves.
Design monitoring and alerting for a fleet of scheduled reports: what would actually tell you a report failed, went stale, or started producing suspicious numbers before a stakeholder notices, and how do you route and escalate those alerts without drowning the on-call person in noise?
Sample Answer
Direct answer
Monitoring and alerting for a fleet of scheduled reports needs to catch three distinct kinds of problem: the job didn't run or failed outright, the data it produced is stale, and the data it produced looks statistically wrong even though the job technically succeeded, each of which needs a different signal and a different alert, routed and prioritized so the on-call person isn't drowning in low-value noise.
Structured elaboration
What to actually collect: job success rate and runtime (a job that succeeds but takes three times longer than usual is an early warning before it starts failing outright), freshness latency (how far behind is the data this report is showing, measured against when it should have refreshed), and a drift or anomaly score on the key output values themselves (did this report's headline number move far outside its normal range compared to recent history).
Alert thresholds: static thresholds work for some things (job failed = alert, full stop) but freshness and drift usually need a range calibrated to the report's own normal variability, not a single global number; a report that normally updates every 15 minutes breaching a 1-hour freshness threshold is a real problem, while a monthly report being '2 hours late' relative to a naive global threshold is meaningless noise.
Routing and escalation: not every alert should page the same person at the same urgency; a hard failure on a widely-viewed executive report escalates fast, while a freshness warning on a low-traffic internal report can go to a queue someone checks during business hours rather than waking anyone up.
Minimizing false positives: an alerting system that cries wolf trains people to ignore it, which is worse than having no alerting at all, so thresholds need periodic tuning against actual incident history (did this alert fire and turn out to matter, or fire and turn out to be nothing) rather than being set once and left alone.
Worked example
An enterprise BI (business intelligence) platform runs 40 scheduled reports with varying cadences. The monitoring setup: every job emits success/failure, runtime, and row-delta-versus-yesterday to a central monitoring table; a job failure on any report triggers an immediate alert, routed by report criticality (the 5 executive-tier reports page the on-call engineer immediately; the other 35 go to a shared Slack channel reviewed each morning); freshness thresholds are set per report based on its own expected cadence (a 15-minute report alerts if it's more than 45 minutes stale, a daily report alerts if it's more than 3 hours late relative to its usual completion time); and a row-count-delta check flags any report whose output row count differs by more than 50% from the prior run, which caught a real incident where an upstream filter change silently dropped most of a report's rows even though the job itself completed successfully with no error.
Trade-offs and pitfalls
Too many alerts at uniform urgency is the single most common failure of a monitoring setup like this: if every one of 40 reports pages the same on-call person at 2 AM for a minor freshness blip, people start ignoring pages, which means the ONE alert that actually mattered gets missed too, so tiering alerts by actual business impact isn't optional polish, it's what keeps the system trustworthy. The other trap is setting drift/anomaly thresholds too tight out of an abundance of caution: a threshold calibrated to catch every possible anomaly also catches normal seasonal variation (a retail report's numbers legitimately spike around a holiday), so thresholds need to account for known seasonality, not just raw statistical variance, or the alert noise problem just moves from 'too many failure alerts' to 'too many false anomaly alerts.'
Design a metric registry (a metrics-as-code system) that becomes the single source of truth for a company's core business metrics, consumed by multiple BI tools. Cover how you would store a metric definition, how ownership and versioning work, how you would test and validate a definition before it publishes, and how a BI tool would fetch the canonical definition instead of re-implementing it.
Sample Answer
Direct answer
A metric registry is a system, not just a spreadsheet: it stores each metric's definition as versioned, testable code (metrics-as-code), records who owns it, and exposes it through an interface that BI (business intelligence) tools query instead of each one reimplementing the calculation. The goal is that 'monthly active users' has exactly one canonical definition in the company, and every tool that shows it is reading that same definition.
Structured elaboration
Storage: the definition itself is usually canonical SQL (a SELECT expression with a defined grain and filters) rather than a proprietary DSL (domain-specific language) when the team wants portability, though some teams do use a declarative format (YAML/JSON describing the aggregation, the join path, and the time grain) that a compiler turns into SQL, which trades some flexibility for stronger validation. Either way, the definition, not just its output, is what's version-controlled.
Ownership and versioning: every metric has a named owner (a person or team), a version history, and a changelog. Changing a metric's definition is a pull-request-style change, not an in-place edit, so you can always answer 'what did this metric mean on March 3rd.'
Testing and validation before publishing: before a new or changed definition ships, it runs through automated checks: does it compile against the current schema, does it produce plausible values against a recent time window (catch an obviously-wrong join before it reaches production), and does it match a manually-verified 'golden' value for a known period if one exists.
How BI tools consume it: rather than each tool having its own calculated field for the metric, the tool queries the registry's API (or a semantic layer built on top of it) for the compiled SQL or the pre-materialized result, tagged with the definition's version. This is what actually prevents drift: the mechanism isn't 'please remember to keep these in sync,' it's 'there is only one place the calculation can be edited.'
Worked example
Suppose active_user is registered as: a user with at least one qualifying event (login, purchase, or content_view) in a trailing 28-day window, deduplicated by user_id, owned by the Growth Analytics team, currently at version 3. Version 2 counted page_view as qualifying; it was deprecated because product decided page views alone were too weak a signal and inflated the count. The registry stores both versions with their date ranges, so a dashboard built before the change and a dashboard built after can each cite which version of active_user they're using, and a historical trend chart doesn't silently jump when the definition changes mid-series, because the registry's compiled query for a given historical date resolves to whichever definition version was live at that time.
Trade-offs and pitfalls
The registry only earns its keep if consumption is enforced, not optional: if a BI tool can still write its own ad-hoc calculated field for active_user alongside the registry's version, you get two competing sources of truth and the registry becomes one more thing to reconcile against rather than the fix. CI validation catches syntax and schema-compatibility problems, but it will not catch a definition that is syntactically fine and semantically wrong (a join that silently fans out rows), so a registry needs periodic value-sanity review, not just automated tests, especially for financially sensitive metrics. And because changing a widely-used metric's definition is now visible and versioned, teams sometimes under-use the registry for exactly that reason: it's easier to fork a private calculated field than to go through review, which quietly defeats the purpose unless the organization treats registry adoption as a real governance requirement, not just infrastructure that exists.
What is a semantic layer in a BI stack, and why do organizations centralize metric logic there instead of letting every dashboard or report define its own calculation? Explain what it typically exposes to consumers, how it connects to the underlying warehouse, and how it helps two different BI tools stay consistent with each other.
Sample Answer
Direct answer
A semantic layer is a translation layer that sits between raw warehouse tables and the tools people use to consume data. It defines metrics, dimensions, hierarchies, and business rules once, in one place, so that a dashboard in one BI (business intelligence) tool and a dashboard in a different BI tool compute 'revenue' or 'active users' the exact same way. Without it, every report author writes their own SQL, and small differences (a different filter, a different join, a different definition of 'active') silently produce different numbers for the same-sounding metric.
Structured elaboration
What it typically exposes to consumers:
- Metrics: named, versioned calculations (e.g.
net_revenue = sum(amount) - sum(refunds)), not raw columns. - Dimensions and hierarchies: the ways a metric can be sliced (region rolling up to country rolling up to sales org), defined once so 'region' means the same thing everywhere.
- Access rules: which rows or columns a given consumer is allowed to see, applied consistently regardless of which tool queries through it.
- Pre-approved custom calculations: a mechanism for an analyst to build something new without duplicating the base metric logic.
How it connects to the warehouse: the semantic layer does not usually store data itself. It holds a model (joins, grain, metric expressions) and compiles a request from a BI tool ("give me net_revenue by region for last quarter") into the actual SQL that runs against the warehouse. The warehouse remains the source of truth for data; the semantic layer is the source of truth for what the data means.
How it keeps two BI tools consistent: both tools query the same semantic layer instead of each maintaining its own copy of the metric logic. If Tableau and Power BI both ask for net_revenue, they get it from the identical compiled definition, not from two independently-written queries that happen to look similar. When the definition changes (say refunds now exclude a new fee type), it changes once and both tools pick it up automatically on their next query, instead of someone having to remember to update two calculated fields in two different tools.
Worked example
Imagine net_revenue is defined once in the semantic layer as: gross order amount, minus refunds, minus disputed chargebacks, at the order-line grain, rolling up through product to product-category to business-unit. An executive dashboard in Power BI asks for net_revenue by business_unit for Q1, and an analyst's ad-hoc exploration in Looker asks for net_revenue by product for the same window. Both queries compile down to the same underlying expression (sum(amount) - sum(refund_amount) - sum(chargeback_amount)), just aggregated to different grains. If someone later discovers refunds should also exclude store-credit reversals, that's one change to the metric definition; both tools reflect it the next time they query, and nobody has to hunt down every dashboard that independently reimplemented 'revenue.'
Trade-offs and pitfalls
A semantic layer is only as trustworthy as its governance: if anyone can add a metric with a name that collides with an existing one, or edit a definition without review, you've just moved the inconsistency problem instead of solving it, which is why most real implementations pair the semantic layer with certified/reviewed definitions and change control. It also adds a layer of indirection: debugging why a number looks wrong now means checking the semantic layer's compiled query, not just the dashboard's visible formula, which can slow down troubleshooting if the team isn't used to it. Finally, a semantic layer that tries to model everything up front becomes a bottleneck; most successful ones start with a small set of high-value, widely-disputed metrics (revenue, active users) and expand rather than modeling the entire warehouse on day one.
Unlock Full Question Bank
Get access to all 34 Business Intelligence, Reporting, and Dashboards interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.