Error Budget Tracking for Analytics Workloads With Variable Query Complexity

Weight analytics query failures by complexity to reveal true infrastructure strain.

· 9 min read
Cover illustration for “Error Budget Tracking for Analytics Workloads With Variable Query Complexity”
SLO Engineering for Analytics · October 23, 2026 · 9 min read · 1,971 words

Tracking the error budget for analytics workloads needs a different unit of account when query complexity varies. Counting failed requests equally hides the strain that heavy queries put on shared infrastructure. A useful framework keeps reliability dimensions separate, weights query failures by complexity, and links that weighted consumption to the owners and the actions they have agreed to take.

Why standard error budgets misrepresent analytics workload reliability

A join over a billion-row set times out, and a row-level lookup fails. Standard request-count accounting counts each as one failure, so both use the same amount of budget. The infrastructure experiences nothing like an equal loss. The join can occupy concurrency slots and consume resources that would otherwise serve many smaller queries, while the lookup has a small blast radius.

The classical error budget is 1 − SLO, expressed as the fraction of requests allowed to fail within a measurement window. The SLI measures service performance, and the SLO sets its target. This abstraction fits relatively homogeneous, user-facing HTTP traffic. Analytics breaks its central assumption because a flat-table query and a multi-hop join over billions of rows can differ by orders of magnitude in cost, latency, and effects on shared capacity.

Variable complexity can degrade freshness, query latency, and concurrency available to other tenants, while slowing joins, window functions, and group-bys across the workload. Demand also arrives in bursts. A single event can trigger simultaneous dashboard refreshes that push compute far beyond its baseline. Without complexity-aware accounting and attribution, the platform team inherits budget consumption it cannot explain, and the warning to slow down arrives late or not at all.

Why a single infrastructure error budget cannot capture what breaks in analytics

Weighting requests cannot fix a budget that combines unrelated failures. Analytics reliability has at least three dimensions that are independent of each other, starting with infrastructure availability, request success, and p95/p99 latency. Even here, averages hide too much. A mean can look fine even when users who run complex queries have a terrible tail experience. Netdata’s SLO framework defines latency SLIs as the ratio of requests faster than a threshold to total valid requests, making threshold violations visible.

Data quality fails on a different axis. A pipeline can be up while it sends out stale data, incomplete features, or data with schema violations. Downstream queries may then give answers that look right but are wrong, without using any infrastructure error budget. For ML-backed analytics, model quality adds another independent dimension, including accuracy against a baseline, low-confidence prediction rates, and feature distribution drift. Engagement can fall even while infrastructure SLOs are green.

Does maintaining separate budgets create too much overhead? The alternative shifts that overhead into incident response. When a composite score deteriorates, responders must first identify the failure’s owner among infrastructure, data engineering, and the ML team. Each dimension therefore needs its own SLI, SLO, budget, owner, and burn-rate alert. That separation establishes what failed before query complexity determines how heavily an infrastructure failure should count.

How query complexity classes define the unit of budget consumption

A stable complexity taxonomy rests on execution characteristics. Most analytical engines expose query execution metadata in system query history, including rows scanned, join depth, window functions, subqueries, estimated versus actual row counts, and memory spilled to disk. These measurements give classification an observable basis. Capturing them at completion allows budget accounting to reflect the work a query performed.

Class A covers lookup and point queries, including selective single-table scans, row-level lookups, and aggregations over small partitions. Their resource consumption and blast radius are low. Class B covers standard analytical work, such as multi-table joins over a moderate number of rows, group-bys with reasonable-cardinality, and window functions over bounded partitions. Class C covers heavy analytical work, including multi-hop joins over very large row counts, full-partition scans, cross-tenant aggregations, large intermediate sets, and unbounded window functions. These queries can saturate concurrency slots and degrade the cluster.

The weight assigned to each class should reflect resources consumed relative to a Class A baseline, using CPU-seconds, memory, and I/O. Direct resource cost is not the whole cost. Because a heavy query can occupy slots that would have served many lookups, the weight should also account for that opportunity cost.

The calculation then uses weighted requests in both parts of the ratio. Failed or slow queries contribute their class weights to the bad-event total, while all valid queries contribute their weights to the denominator. The resulting weighted failure fraction is compared with the allowance set by the SLO. Weighting only failures while leaving the denominator as a raw count would mix incompatible units.

Rolling windows and burn-rate alerts calibrated for complexity-weighted budgets

A 30-day aggregate can look safe while a heavy analytical batch running Tuesday has already consumed the week’s weighted allowance. Heavy-query incidents burn through headroom quickly. A 7-day rolling window exposes degradation that a monthly view can smooth over, while quarterly reviews recalibrate targets against user tolerance, seasonal patterns, and complexity introduced by product changes. The shorter window changes how quickly sustained pressure becomes visible while leaving the underlying good-event ratio unchanged.

Burn-rate alerts then need confirmation across two windows. A short window detects rapid consumption, while a longer window distinguishes sustained degradation from a brief Class C spike. The supplied multi-window pattern uses a 14.4x threshold that must be crossed in both a 1-hour window and a 5-minute window simultaneously. A separate alert works on its own and uses a lower burn rate across a pair of wider windows. Those patterns need analytics-specific calibration rather than treating the example threshold as a universal setting.

Burn that would use up the window’s allowance within roughly two days calls for a page right away, often because Class C queries keep failing or hold concurrency slots for a long time. Moderate burn that keeps going calls for a ticket and a review by the team. Slow burn that threatens exhaustion within the window belongs on a trend watch for query optimization.

The weight belongs inside the SLI calculation. Datadog’s error budget alert documentation provides an implementation reference for attaching alerts to SLOs. Pacing alerts add another useful view by projecting consumption to the end of the window. Databricks describes the analogous cost-budget pattern of firing every four hours and routing to Slack, giving teams days to right-size a warehouse, optimize a query, or defer a batch.

Attribution: connecting weighted budget consumption to the query and team that caused it

A shared BI warehouse may serve dozens of dashboards, several transformation models, and a stream of ad hoc queries. Warehouse-level usage shows where compute was consumed, but not necessarily which query or team caused a Class C incident. That distinction determines who can respond. A weighted budget becomes actionable only when each draw connects to a specific query, warehouse, and owner.

The attribution model needs two layers. At the warehouse level, tags assigned at creation identify the team, cost center, and use case, such as BI serving, ad hoc analysis, or scheduled refresh. In Databricks, those tags propagate to system billing and usage tables. At the query level, query tags add business context alongside the executor identity and statement ID in system query history. Warehouse tags establish ownership of the compute, while query tags explain the particular workload that consumed it.

This discipline has to survive ordinary provisioning. Databricks has no native policy preventing untagged warehouse creation, so the recommended approach is infrastructure-as-code with tags in the definition, UI creation treated as an exception, and a regular attribution-gap query. The ownership model must be equally explicit. The platform team owns the infrastructure budget, data engineering owns data quality, and each team owns its share of the weighted query budget. Repeated Class C work then draws on that team’s budget instead of getting lost in the platform’s shared request count.

How agentic query patterns stress complexity-weighted budgets in ways human workloads do not

AI agents are database users whose activity differs structurally from human dashboard traffic. An agent translates a natural-language request into a query, executes it, checks whether the result matches the intent, and refines the query when the output is incomplete. One intent can produce many database requests. Production agentic retrieval already involves dynamic calls, multi-hop reasoning, self-checks, and re-retrieval after failure, multiplying volume and complexity against shared analytical capacity.

Not every agent query is Class C. Individually modest probes can collectively consume concurrency, while heavier refinements add direct Class C pressure. A budget that considers only the apparent size of the originating user request misses both effects. Agents therefore need their own allocation, separate from human dashboard workloads, so their iterative activity does not silently consume interactive capacity. Read-only, isolated compute keeps heavy agent probes from competing with human lookups for the same slots.

Write access introduces a different hazard. An agent might respond to a slow query by inspecting the schema, creating an index, and rerunning the workload. That autonomous schema change can invalidate query plans across the cluster and spend substantial budget beyond the agent’s own session. Agents should start on isolated, read-only compute before write or DDL permissions are allowed. Sandboxed branches then give them room to try things against real data without changing production query plans or using the production SLO’s budget.

Attribution must follow the whole agent session. Every agentic query needs the agent identity, originating intent, and query text so its budget draw remains auditable. MCP has become a standard access protocol for agents, but a database sees only part of an agent’s activity when the session also uses files, CRM, and search tools. OpenTelemetry GenAI semantic conventions include MCP-specific trace attributes that connect MCP-call traces to the full session trace. That connection makes database consumption visible in the context of the reasoning process that generated it.

Acting on a complexity-weighted budget: the policy decisions that make it operational

Teams need to agree on consequences before an alert fires. A policy document needs named owners, tier triggers, required actions, and explicit override authority. Netdata calls this a “pre-negotiated contract between stakeholders”. Without that agreement, teams still have to negotiate whether reliability work outranks feature work during the incident. With it, budget health becomes a shared basis for query admission and feature velocity.

Yellow means moderate weighted burn, and the team must review it within one business day. The review identifies the query class driving consumption and flags candidate Class C queries for optimization. There is no deployment freeze at this tier. But features that add new Class C patterns need sign-off, so the added complexity gets a close look before it adds to the pressure already there.

Orange means fast weighted burn and changes admission policy. Class C queries are throttled or queued, concurrency limits are tightened, and agentic sessions move to sandboxed compute if they are not already isolated. Optimization work becomes a blocking priority. Queueing heavy queries protects Class A and B concurrency while giving the system time to recover and exposing the cost to the submitting team.

Red applies when the budget is near exhaustion or projected to exhaust within the window. Deployments that add query complexity are frozen, and Class C admission remains gated through a queue. On-call owns both the weighted budget and uptime. A mandatory post-incident review includes the complexity taxonomy, while a healthy budget permits teams to deploy freely, including features that add analytical complexity.

Chronic Class C burn calls for a different response. If heavy queries repeatedly exhaust the allowance, tighter admission controls alone cannot resolve the mismatch between the workload and available concurrency. The budget then points to a need to change the architecture, including splitting compute by complexity class and moving hot data off S3 into a memory layer so heavy scans stop re-reading cold partitions each time they run. At that point, the budget is identifying where the infrastructure needs to change.

Sources

  1. Error Budget Alerts

More in SLO Engineering for Analytics