How We Built Query Scheduling and Priority Management for Multi-Tenant Observability

Table of Contents

It's 9:15 AM. Every engineering team in the company has just opened their dashboards. The alerting system is evaluating hundreds of queries on its normal cadence. And a platform engineer just kicked off an ad hoc query scanning 30 days of metrics for a capacity planning report. That query consumes enough resources to slow down everything else. Dashboards spin. Alert evaluations lag. Three teams open tickets asking why their monitoring is degraded.

This is the noisy neighbor problem in multi-tenant observability. It shows up at the query layer (one expensive query starving others), at the ingestion layer (one misconfigured service flooding the pipeline), and at the intersection (a heavy ingestion load degrading query performance because they share compute). Solving it at only one layer doesn't work. The problem leaks through wherever the isolation is weakest.

In this post, we'll walk through how Kloudfuse addresses query scheduling and priority management across the full stack: stream-level ingestion isolation, filter-based prioritization within streams, workload separation between ingestion and query, scheduled views for pre-computation, and query safety guardrails for AI-generated queries.

Why Single-Layer Query Scheduling Isn't Enough

Most observability platforms address the noisy neighbor problem at the query layer. They implement per-tenant query queues, fair scheduling across tenants, and query timeouts. Grafana Loki, for example, maintains separate FIFO queues per tenant and assigns querier workers to these queues for execution fairness.

This helps, but it only protects against one class of noisy neighbor: the expensive query. It doesn't help when:

  • A canary deployment starts emitting high-cardinality metrics and saturates the ingestion pipeline, causing metric lag that affects every team's dashboards

  • A log flood from one service consumes so much storage I/O that query latency degrades for all telemetry types

  • Ingestion and query compete for the same compute, so a spike in either dimension degrades the other

Kloudfuse addresses this by implementing priority management at multiple layers of the stack, so no single layer becomes the bottleneck.

How Does Stream-Level Ingestion Priority Work?

Each of the five telemetry streams (metrics, logs, traces, events, RUM) flows through a dedicated ingestion pipeline with independent resource allocation. This is the Pinot Stream Isolation architecture.

The practical impact: a log flood does not affect metrics ingestion capacity. A traces spike does not throttle events. Each stream has its own rate limit and burst allowance, configured independently.

Rate and burst work together. The rate defines steady-state throughput. The burst allowance handles short-term spikes. Setting burst = rate * 10 means the system absorbs a 10-second spike without throttling. When the burst allowance is exhausted, excess telemetry is dropped (not queued indefinitely, which would create backpressure that cascades upstream).

The throttling happens at ingestion time, not billing time. Within seconds of a misconfigured service emitting excessive metrics, the rate control activates. Production monitoring from every other service continues unaffected.

How Does Filter-Based Prioritization Work Within a Stream?

Stream isolation prevents cross-stream interference, but what about prioritization within a stream? Not all metrics are equally important. Production data matters more than development environment noise. Critical service traces matter more than experimental canary deployments.

Kloudfuse supports filter-based prioritization using the same Kubernetes labels, service tags, and custom attributes already used for organization. You can configure class rules that split a stream's quota across custom-defined classes:

  • Prioritize environment=production metrics

  • Prioritize logs from tier=critical services

  • Prioritize traces matching namespace=checkout

When ingestion approaches the configured limit, high-priority data continues flowing while lower-priority data gets throttled first. This is configured via UI, CLI, or API, and the class definitions use the same label vocabulary that teams already apply to their services.

The design decision here was to reuse existing labels rather than introduce a separate priority taxonomy. Teams already spend significant effort labeling their Kubernetes resources. Requiring a parallel priority labeling scheme would add configuration burden and create drift between how services are organized and how they're prioritized.

How Does Workload Isolation Separate Ingestion from Queries?

Kloudfuse 4.0 introduced workload isolation: the ability to separate ingestion, query, and control plane into independently scalable components. Each workload gets its own resource allocation, tunable via Helm values.

CTO Ashish Hanwadikar summarized the motivation: "Ingestion, query, and control plane workloads do not behave the same way, so they should not be forced to scale the same way. Treating them as shared compute creates architectural debt."

The practical implications:

  • Tune ingestion memory without degrading query performance. A metrics spike that requires more ingestion memory doesn't starve the query layer.

  • Scale query capacity during business hours without over-provisioning ingestion during off-peak. Dashboard-heavy mornings get more query resources. Overnight batch processing gets more ingestion resources.

  • Isolate control plane operations. Configuration changes, RBAC updates, and platform management don't compete with data processing.

This is the infrastructure-level complement to the logical isolation provided by RBAC and stream isolation. A noisy ingestion source can't degrade query performance because they don't share compute. Combined with stream-level rate limiting, it creates a two-tier defense: stream isolation prevents cross-stream ingestion interference, and workload isolation prevents ingestion-to-query interference.

How Do Scheduled Views Optimize Repeated Queries?

Many observability queries follow patterns. The same services, same time windows, same aggregations, executed by multiple teams multiple times per day. Scheduled views capture these patterns as pre-aggregated datasets.

A scheduled view is a FuseQL query that executes automatically on a configurable schedule (from every minute to hours or days). Results are materialized back into queryable tables in the OLAP engine, accessible via _view=<view_name> in subsequent queries.

The performance impact is significant. Log pattern analysis queries that previously scanned millions of data points and took 15-20 seconds now return in under one second. Cost analysis queries for chargeback models load instantly. Cross-telemetry views correlating service error rates with infrastructure CPU usage become responsive enough for interactive dashboards.

In Kloudfuse 4.0, scheduled views gained historical data backfill. You can specify a start time, and the view catches up automatically with historical data. Previously, a scheduled view only captured data from its creation time forward. Backfill eliminates the "we should have created this view last week" regret.

Additional capabilities: pause and resume with automatic catch-up, folder-based organization with RBAC integration (so views respect the same access control as dashboards), bulk operations, and a GraphQL API for programmatic management.

The tradeoff between scheduled views and raw queries is freshness. A scheduled view updated every minute has up to one minute of staleness. For high-level dashboards where a minute of delay is acceptable, the 10x performance improvement is worth it. For real-time troubleshooting where every second matters, raw queries provide immediate data.

How Does Query Safety Mode Protect Against AI-Generated Query Overload?

The MCP Server introduces a new class of query source: AI agents generating queries from natural language prompts. These queries are syntactically valid (the AI knows PromQL and FuseQL) but can be operationally dangerous.

An engineer asking "show me all metrics for the last month" might expect a summary. The AI might generate a query that selects every metric without filters, at fine resolution, across a 30-day range. Without guardrails, that query would be equivalent to a denial-of-service attack on the query infrastructure.

Query Safety Mode validates every AI-generated query before execution:

  • Bare selector rejection: Queries without any label filter (no namespace, service, or status code) are rejected

  • Lookback ratio limits: Queries where the time range is disproportionate to the resolution are flagged

  • Data point caps: Queries exceeding a configurable threshold are rejected pre-execution

The rejected query returns a specific error message that the AI uses to reformulate. This is a feedback loop: the AI learns from each rejection and generates progressively better-scoped queries within the conversation.

How Does Consumption Tracking Enable Accountability?

Beyond technical controls, Kloudfuse provides consumption tracking dashboards showing exactly what is being ingested, from where, and by whom. Breakdowns are available by stream, by service, by team, and by any custom tracking label.

This enables chargeback models where teams are accountable for their observability resource usage. The behavioral effect is real: teams that see their usage attributed to them tend to add appropriate sampling, reduce retention for non-critical data, and instrument with intention rather than "log everything and hope for the best."

Consumption tracking doesn't replace technical controls. A team that's aware of their usage but can't control a sudden spike still needs rate limiting to prevent impact on others. The two mechanisms are complementary: technical controls provide immediate protection, and consumption visibility provides the feedback loop for sustainable behavior change.

What Does the Full Priority Stack Look Like?

Putting it all together, query scheduling and priority in Kloudfuse operates at five layers:

Layer

Mechanism

What It Protects Against

Stream isolation

Independent ingestion pipelines per telemetry type

Cross-stream interference (log flood affecting metrics)

Filter-based priority

Label-based class rules within each stream

Critical data being throttled alongside noise

Workload isolation

Independent compute for ingestion, query, control plane

Ingestion spikes degrading query performance

Scheduled views

Pre-computed query results on configurable schedules

Repeated expensive queries consuming resources

Query Safety Mode

Pre-execution validation of AI-generated queries

Unbounded queries from AI agents

Each layer addresses a different failure mode. No single layer is sufficient on its own, but together they provide comprehensive protection against the noisy neighbor problem across the full observability stack.

The Design Decision: Multi-Layer Over Single-Layer

The alternative to this approach is a single, sophisticated query scheduler that manages all resource allocation centrally. This would be simpler to reason about and configure but would require the scheduler to understand and manage resources across ingestion, query, and storage simultaneously.

We chose the multi-layer approach because each layer operates at a different timescale and requires different tradeoffs. Ingestion rate limiting needs to react in seconds. Workload isolation needs to adjust over minutes to hours. Scheduled views operate on a minute-to-day cadence. Query Safety Mode evaluates per-query in milliseconds.

A unified scheduler that handles all these timescales would need to be significantly more complex than any individual layer. And it would be a single point of failure: if the scheduler itself is overloaded or misconfigured, all protection is lost simultaneously. The layered approach ensures that failure in one layer doesn't cascade. If scheduled views stop updating, the other layers still protect against resource exhaustion.

Next Steps

The rate control configuration guide covers stream-level ingestion limits and filter-based prioritization. The scheduled views documentation walks through creating and managing pre-computed views.

How does your team handle the morning dashboard rush? Do you have query-level controls, or are you relying on "please don't run expensive queries during business hours" Slack messages? We'd like to hear what's working and what's still causing pain.

Observe. Analyze. Automate.

logo for kloudfuse

Observe. Analyze. Automate.

logo for kloudfuse

Observe. Analyze. Automate.

logo for kloudfuse