Compile Ready
All system design questions
System Design/Foundations

Monitoring System

Design an end-to-end monitoring and alerting platform with dashboards, thresholds, and on-call routing.

Intermediate 50m interview 21m read High frequency Popularity 79
Amazon Microsoft Netflix

Problem Statement

Design a Monitoring System like Datadog, New Relic, or Azure Monitor. The platform receives telemetry from applications, hosts, containers, cloud services, and synthetic probes, then turns that telemetry into dashboards, alerts, SLOs, error budgets, traces, logs, and incident notifications.

At interview scale, assume a multi-tenant SaaS product with thousands of customer teams, hundreds of thousands of monitored resources, and large bursts during incidents. The core challenge is not pure metrics collection; this system consumes metrics, logs, traces, and health checks, correlates them, evaluates alert rules over time windows, suppresses noise, and routes actionable incidents to the right on-call owner.

The default design should optimize for reliable ingestion, bounded query latency, correct alert evaluation, durable incident history, and alert fatigue reduction. Optional advanced features such as anomaly detection, service maps, synthetic monitoring, and SLO burn-rate alerts should layer on top of the same telemetry and alerting foundations.

Business use case

Engineering and operations teams use monitoring platforms to detect outages before customers complain, understand regressions after deploys, and measure whether services are meeting reliability targets. A strong platform shortens mean time to detect and mean time to recover by bringing metrics, logs, traces, dashboards, and paging workflows into one place.

For businesses, observability protects revenue and trust. It helps teams enforce SLOs, prioritize reliability work using error budgets, reduce noisy alerts, and give executives a shared view of service health across products, regions, and customer tiers.

Functional Requirements

  • Ingest metrics from agents, OpenTelemetry collectors, application SDKs, and cloud integrations.

  • Ingest logs and traces, preserve correlation fields such as service, environment, host, trace ID, and request ID.

  • Store and query time-series data with tags, rollups, retention tiers, and dashboard-friendly aggregations.

  • Search logs and traces by time range, service, severity, labels, trace ID, and sampled request attributes.

  • Let users create dashboards with charts, service health panels, trace waterfalls, log widgets, and SLO widgets.

  • Evaluate alert rules over sliding windows for thresholds, missing data, anomaly signals, synthetic checks, and burn-rate conditions.

  • Deduplicate, group, silence, acknowledge, and resolve alerts to reduce alert fatigue and flapping.

  • Route notifications through escalation policies to email, Slack, Teams, webhooks, and PagerDuty-style on-call systems.

Non-Functional Requirements

Ingestion latency

Fresh telemetry should become queryable within 10 to 30 seconds for metrics and within 30 to 60 seconds for logs and traces. Alert evaluation should detect most threshold violations within one evaluation interval after the relevant window closes.

Alert availability

The alerting path must be more reliable than dashboards. During a partial outage, ingestion and alert evaluation for critical metrics should continue even if expensive log search, trace exploration, or non-critical dashboards are degraded.

Scalability and cardinality control

The system must handle millions of samples per second while protecting itself from unbounded tag cardinality. Tenant quotas, label allow lists, rollups, sampling, and backpressure are required so one customer or one bad deploy cannot exhaust shared storage.

Query performance

Common dashboard queries over recent rollups should complete in under 1 second p95. Wider exploratory queries over raw logs, high-cardinality metrics, or long trace windows can be slower but should have timeouts, result limits, and progressive loading.

Durability and retention

Telemetry can be lossy under extreme pressure, but alert state, rule definitions, SLO definitions, audit logs, and incident history must be durable. Metrics, logs, and traces need configurable retention tiers with replication and backups for customer commitments.

Correctness and idempotency

The ingestion path should tolerate retries without double-counting counters or creating duplicate log batches. Alert evaluation must use stable windows, handle late data explicitly, and avoid repeatedly paging the same incident unless escalation policy requires it.

Multi-tenancy and isolation

Tenants need strict data isolation, separate quotas, per-team RBAC, and noisy-neighbor protection. Query, ingestion, and alerting capacity should be partitioned enough that a large customer's incident does not delay smaller customers' critical alerts.

Capacity Estimation

Assumptions

Assume 100,000 monitored resources across hosts, containers, serverless functions, databases, and managed cloud services. Each resource emits 200 active metric series on average, sampled once every 10 seconds. Assume logs average 1 KB per second per resource after filtering, and traces are sampled to 500,000 spans per second across the fleet.

Assume 80 bytes per encoded metric sample before compression, 250 bytes per sampled trace span after basic attribute pruning, 30 days of log retention, 45 days of metric retention, 7 days of raw trace retention, 200,000 active alert rules, and a 10x burst multiplier during large incidents or regional outages.

Monitored resources

100,000 resources

Hosts, containers, services, databases, and synthetic checks

Active metric series

20M series

100,000 resources times 200 active series

Average metric ingest

2M samples per second

20M active series sampled once every 10 seconds

Peak metric ingest

20M samples per second

10x burst during incidents, autoscaling events, or bad deployments

Metric storage

155 TB compressed for 45 days

2M samples per second times 80 bytes, compressed about 4:1

Log ingest

100 MB per second

100,000 resources times 1 KB per second

Log storage

86 TB compressed for 30 days

8.6 TB raw per day compressed about 3:1

Trace ingest

500K spans per second

Sampled spans after head or tail sampling policies

Trace storage

76 TB compressed for 7 days

500K spans per second times 250 bytes for 7 days

Alert evaluations

3,300 evaluations per second

200,000 alert rules evaluated once per minute

Dashboard query traffic

5,000 peak QPS

Interactive dashboards, incident war rooms, and API consumers

Calculations

  • Metric series: 100,000 monitored resources times 200 active series is 20M active series.
  • Metric ingest: 20M series sampled once every 10 seconds is 2M samples per second on average. A 10x burst gives 20M samples per second.
  • Metric storage: 2M samples per second times 80 bytes is 160 MB per second raw. That is about 13.8 TB per day raw. With 4:1 compression, store about 3.45 TB per day. Over 45 days, reserve about 155 TB before replicas and index overhead.
  • Log ingest: 100,000 resources times 1 KB per second is 100 MB per second. That is about 8.6 TB per day raw. With 3:1 compression over 30 days, reserve about 86 TB before replicas and search index overhead.
  • Trace ingest: 500,000 sampled spans per second times 250 bytes is 125 MB per second. That is about 10.8 TB per day. Over 7 days, reserve about 76 TB before replication.
  • Alert evaluations: 200,000 active rules evaluated every 60 seconds means about 3,333 rule evaluations per second. The engine should evaluate from precomputed rollups rather than scanning raw samples.
  • Notifications: if 1 percent of alert rules fire during a major outage, that is 2,000 initial alert events. Grouping by service, region, and severity should collapse this into far fewer incidents before paging humans.

API Design

POST/api/v1/telemetry/metrics

Receives batches of metric samples from agents, collectors, SDKs, or cloud integrations. The gateway authenticates the tenant, validates label limits, and writes the accepted batch to the ingestion stream.

Request


{
  "tenantId": "tenant_123",
  "source": "otel-collector",
  "samples": [
    {
      "metric": "http.server.duration.p95",
      "timestamp": "2026-07-26T06:59:00Z",
      "value": 183,
      "tags": {
        "service": "checkout",
        "region": "us-east-1",
        "environment": "prod"
      }
    }
  ]
}

Response


{
  "accepted": 4800,
  "rejected": 12,
  "nextAllowedAt": "2026-07-26T06:59:10Z"
}
  • 202Batch accepted for asynchronous processing
  • 400Malformed payload or invalid metric name
  • 401Invalid ingestion token
  • 413Batch too large
  • 429Tenant ingestion quota exceeded
POST/api/v1/telemetry/logs

Accepts structured log batches. Logs should already be redacted by agents where possible, but the server also applies schema validation, tenant quotas, and optional sampling.

Request


{
  "tenantId": "tenant_123",
  "logs": [
    {
      "timestamp": "2026-07-26T06:59:05Z",
      "service": "checkout",
      "severity": "ERROR",
      "traceId": "tr_abc123",
      "message": "Payment authorization timed out",
      "attributes": {
        "region": "us-east-1",
        "deploy": "2026.07.26.4"
      }
    }
  ]
}

Response


{
  "accepted": 1000,
  "sampledOut": 200,
  "redactedFields": ["card_number"]
}
  • 202Logs accepted
  • 400Invalid log schema
  • 401Invalid ingestion token
  • 429Log ingestion quota exceeded
POST/api/v1/telemetry/traces

Receives trace spans in batches. The system preserves parent-child relationships, indexes trace IDs, and supports head or tail sampling depending on tenant policy.

Request


{
  "tenantId": "tenant_123",
  "spans": [
    {
      "traceId": "tr_abc123",
      "spanId": "sp_1",
      "parentSpanId": "sp_0",
      "service": "checkout",
      "operation": "POST /checkout",
      "startTime": "2026-07-26T06:59:01Z",
      "durationMs": 742,
      "status": "error"
    }
  ]
}

Response


{
  "accepted": 520,
  "sampleRate": 0.1
}
  • 202Spans accepted
  • 400Invalid trace payload
  • 401Invalid ingestion token
  • 429Trace ingestion quota exceeded
POST/api/v1/query

Runs a dashboard or exploration query across time-series, logs, traces, or correlated telemetry. The query service enforces RBAC, tenant limits, timeouts, and maximum result sizes.

Request


{
  "tenantId": "tenant_123",
  "queryType": "timeseries",
  "expression": "p95:http.server.duration{service=checkout,environment=prod}",
  "from": "2026-07-26T06:00:00Z",
  "to": "2026-07-26T07:00:00Z",
  "resolutionSeconds": 60
}

Response


{
  "series": [
    {
      "labels": {
        "service": "checkout",
        "environment": "prod"
      },
      "points": [
        { "timestamp": "2026-07-26T06:59:00Z", "value": 183 }
      ]
    }
  ],
  "partial": false
}
  • 200Query completed
  • 206Partial result returned before timeout
  • 400Invalid query expression
  • 403Caller lacks access to the requested tenant or resource
  • 429Query rate limit exceeded
POST/api/v1/alert-rules

Creates an alert rule using a time-series query, evaluation interval, window, threshold, grouping labels, no-data behavior, and routing policy.

Request


{
  "tenantId": "tenant_123",
  "name": "Checkout p95 latency too high",
  "query": "p95:http.server.duration{service=checkout,environment=prod}",
  "window": "5m",
  "evaluationInterval": "1m",
  "condition": {
    "operator": ">",
    "threshold": 500
  },
  "groupBy": ["service", "region"],
  "silenceWindows": [],
  "route": "payments-primary-oncall"
}

Response


{
  "ruleId": "rule_456",
  "state": "enabled",
  "nextEvaluationAt": "2026-07-26T07:00:00Z"
}
  • 201Alert rule created
  • 400Invalid rule or query
  • 403Caller cannot create alert rules for this tenant
  • 409Duplicate rule name in this scope
PATCH/api/v1/incidents/{incidentId}

Acknowledges, resolves, reassigns, or silences an active incident. This endpoint changes alert state and escalation behavior, not historical telemetry.

Request


{
  "action": "silence",
  "durationMinutes": 60,
  "reason": "Known deploy rollback in progress",
  "actor": "user_789"
}

Response


{
  "incidentId": "inc_789",
  "state": "silenced",
  "silencedUntil": "2026-07-26T08:00:00Z"
}
  • 200Incident state updated
  • 400Invalid action
  • 403Caller cannot modify this incident
  • 404Incident not found
  • 409State transition is no longer valid

Ingestion APIs are asynchronous because the gateway should validate, quota-check, and enqueue telemetry quickly. Query and configuration APIs are synchronous because users expect immediate feedback when saving dashboards, rules, silences, and SLO definitions.

The monitoring system should support OpenTelemetry, Prometheus remote write, syslog-style log forwarding, and cloud provider integrations at the edge, but the internal API should normalize all formats into a tenant-aware telemetry envelope.

Database Design

The system uses different storage engines for different access patterns. Metrics are optimized for time-range scans and rollups, logs are optimized for text and attribute search, traces are optimized for trace ID lookup and service graph analysis, and alert state is optimized for durable state transitions.

The relational-looking schema below describes logical entities. At production scale, the metric and event tables map to a distributed time-series store, columnar object storage, and search indexes rather than one monolithic relational database.

metric_series
series_iduuidStable identifier derived from tenant, metric name, and normalized tag set
tenant_iduuidTenant partition and authorization boundary
metric_namevarchar(255)Canonical metric name after normalization
tag_hashbinary(16)Hash of sorted tags for fast lookup and deduplication
tag_setjsonBounded set of dimensions such as service, region, host, and environment
retention_tiervarchar(32)Raw, hourly rollup, daily rollup, or premium long retention
first_seen_attimestampFirst sample time
last_seen_attimestampMost recent accepted sample time
metric_chunks
tenant_iduuidPartition key prefix
series_iduuidMetric series identifier
bucket_starttimestampStart of the compressed time bucket
resolution_secondsintRaw or rollup resolution
encoded_samplesblobCompressed samples using delta and Gorilla-style encoding
min_valuedoublePrecomputed minimum for faster aggregations
max_valuedoublePrecomputed maximum for faster aggregations
sum_valuedoublePrecomputed sum for rate and average calculations
sample_countbigintNumber of samples in the bucket
telemetry_event_index
tenant_iduuidTenant partition
event_typevarchar(16)Log or span
event_timetimestampEvent timestamp
servicevarchar(255)Service name for filtering and correlation
severityvarchar(32) nullableLog severity when event is a log
trace_idvarchar(64) nullableTrace identifier for logs and spans
span_idvarchar(64) nullableSpan identifier when event is a trace span
attributesjsonIndexed bounded attributes
object_keyvarchar(512)Pointer to compressed raw payload in object storage
alert_rules
rule_iduuidPrimary key
tenant_iduuidTenant owner
namevarchar(255)Human-readable rule name
querytextTime-series or synthetic check expression
evaluation_interval_secondsintHow often the rule evaluates
window_secondsintLookback window for the condition
conditionjsonThreshold, anomaly, no-data, or burn-rate condition
group_byjsonLabels used for alert grouping
route_iduuidNotification route or escalation policy
enabledbooleanWhether the rule is active
alert_incidents
incident_iduuidPrimary key for an alert incident
tenant_iduuidTenant boundary
rule_iduuidAlert rule that produced the incident
fingerprintvarchar(255)Deduplication key derived from rule, tenant, and grouping labels
statevarchar(32)Triggered, acknowledged, silenced, resolved, or suppressed
severityvarchar(32)Page, ticket, warning, or info
started_attimestampFirst time the condition became active
last_fired_attimestampMost recent evaluation that matched
dedupe_countbigintNumber of repeated firings collapsed into this incident
silenced_untiltimestamp nullableSilence expiry if active

Indexes

  • metric_series.tenant_id, metric_name, tag_hash supports series lookup during ingestion and query planning.
  • metric_chunks.tenant_id, series_id, bucket_start is the primary access path for dashboard and alert window scans.
  • telemetry_event_index.tenant_id, event_time, service supports recent log and trace exploration by service and time.
  • telemetry_event_index.trace_id supports direct trace waterfall retrieval and log-to-trace correlation.
  • alert_rules.tenant_id, enabled lets scheduler shards find active rules for a tenant.
  • alert_incidents.tenant_id, fingerprint, state enforces deduplication of active incidents.

Relationships

Each tenant owns metric series, event indexes, alert rules, dashboards, notification routes, SLOs, and incidents. Alert rules reference metric queries or synthetic check streams and create alert incidents through a dedupe fingerprint. Logs and spans share correlation identifiers so a dashboard point can jump to related logs or a trace waterfall without joining on the ingestion hot path.

NoSQL alternatives

Metrics are usually stored in a specialized time-series database or columnar store such as M3, Cortex, Thanos, VictoriaMetrics, ClickHouse, Druid, Bigtable, or a custom LSM-backed TSDB. Logs fit object storage plus a search index or columnar lake. Traces fit a span store indexed by trace ID, service, operation, and time.

Rule definitions, silences, routes, SLO definitions, audit logs, and incident state can live in a strongly consistent relational database or a replicated key-value store because they are smaller but more correctness-sensitive than raw telemetry.

High-Level Architecture

Drag to pan · Ctrl/⌘ + scroll to zoom

Telemetry ingestion flows from monitored workloads through agents, gateways, queues, processors, and specialized stores. Dashboards query the stores, while alert evaluation reads rollups, updates durable alert state, and sends grouped incidents to notification routing.

The architecture separates the ingestion path, query path, and alerting path. Ingestion must absorb bursts, normalize formats, enforce tenant quotas, and fan telemetry into the right stores. Query APIs serve dashboards and investigations, but they should not sit on the critical alert paging path.

Metrics, logs, and traces have different storage needs. Metrics use a time-series store with compressed chunks and rollups. Logs and traces use object storage plus searchable indexes. Correlation comes from shared labels, trace IDs, service names, deploy versions, and timestamps rather than from forcing all telemetry into one database.

Alerting is a first-class subsystem. The alert engine reads precomputed rollups, evaluates rules on stable windows, deduplicates by fingerprint, respects silences and maintenance windows, and hands incidents to the notification router for escalation.

Request Flow

  1. 1

    Telemetry is emitted by workloads

    Applications, hosts, containers, managed services, and SDKs emit metrics, logs, and spans. Agents and OpenTelemetry collectors batch data locally, attach tenant and environment metadata, redact obvious secrets, and retry on transient network failures.

  2. 2

    Synthetic checks create health signals

    Regional probers run HTTP checks, TCP checks, browser flows, and API canaries against customer endpoints. Their results are converted into metrics and events so they can drive dashboards, alerts, and SLO calculations alongside application telemetry.

  3. 3

    Ingestion gateway validates and queues

    The gateway authenticates the ingestion token, checks tenant quotas, validates schema, rejects dangerous label explosions, and writes accepted batches to the telemetry bus. It returns 202 after durable enqueue rather than waiting for downstream indexing.

  4. 4

    Stream processors normalize telemetry

    Consumers parse formats, normalize units, compute derived fields, enforce sampling policies, drop or quarantine malformed payloads, and attach routing keys. They also compute metric rollups so dashboards and alert rules do not scan raw samples for common windows.

  5. 5

    Metrics, logs, and traces land in specialized stores

    Metric chunks are written to the time-series store by tenant, series, and time bucket. Logs and spans are compressed into object storage and indexed by time, service, severity, trace ID, and selected attributes for search and correlation.

  6. 6

    Dashboards query recent rollups

    An operator opens a dashboard. The query API authorizes access, plans queries against the right rollup resolution, fans out to metric and event stores when needed, and returns partial results if a large panel exceeds its timeout.

  7. 7

    Alert rules evaluate on schedules

    Scheduler shards assign active rules to alert workers. Each worker reads the relevant rollup window, applies threshold or burn-rate logic, handles no-data behavior, and writes a stable evaluation result with a rule and group fingerprint.

  8. 8

    Alert state is deduplicated and grouped

    The alert engine checks existing incidents, suppression rules, silences, maintenance windows, and flapping dampeners. Repeated firings update the same incident rather than paging every minute, while resolved evaluations close incidents after a recovery window.

  9. 9

    Notifications route through escalation policies

    Actionable incident events go to the notification router. It selects the on-call team, delivery channel, retry policy, escalation delay, and fallback contact, then sends pages, chat messages, tickets, or webhooks with links back to dashboards and traces.

Core Components

Agents and OpenTelemetry Collectors

Collect local telemetry and forward it reliably.

Agents scrape metrics, tail logs, receive spans, attach resource metadata, redact sensitive fields, batch payloads, and retry with backoff. They should buffer locally for short outages but shed low-priority telemetry when disk limits are reached.

Ingestion Gateway

Protects the platform from invalid, unauthenticated, or excessive telemetry.

The gateway verifies tokens, maps requests to tenants, enforces rate and cardinality quotas, validates schemas, applies backpressure, and durably appends accepted data to the telemetry bus. It keeps customer-facing ingestion stable even when processors scale up or recover.

Telemetry Bus

Decouples ingestion spikes from downstream processing.

Kafka, Kinesis, Pulsar, or Pub/Sub buffers metric, log, trace, and synthetic streams by tenant and telemetry type. Retention on the bus provides replay during processor failures and allows separate consumers for storage, alerting, anomaly detection, and billing.

Metrics Pipeline and Time-Series Store

Stores compressed samples and rollups for dashboards and alerts.

The metrics pipeline deduplicates retries, computes rates and percentiles where appropriate, down-samples old data, and stores compressed chunks. The store is partitioned by tenant, metric, series hash, and time to support efficient range scans.

Log and Trace Store

Supports search, trace waterfall retrieval, and cross-telemetry correlation.

Logs and spans are written to compressed object storage and indexed for recent search. Trace IDs provide direct lookup, while service, operation, severity, deployment, and request attributes support incident investigation.

Alert Evaluation Engine

Evaluates rules, SLO burn rates, missing data, and synthetic check failures.

Alert workers evaluate rules on fixed schedules using precomputed rollups, handle late data policies, compute incident fingerprints, suppress flapping, and update durable alert state. They must be deterministic enough that retries do not create duplicate pages.

Notification Router and Escalation Manager

Turns alert incidents into targeted human notifications.

The router applies routing rules, team ownership, severity policies, on-call schedules, retries, escalation chains, and channel preferences. It integrates with PagerDuty-style systems, Slack, Teams, email, SMS, tickets, and customer webhooks.

Dashboard and Query API

Provides interactive visualization and investigation workflows.

The API plans queries, chooses raw or rollup resolution, merges metrics with related logs and traces, enforces RBAC, caches common panels, and returns progressive or partial results for expensive investigations.

Deep Dive

Metrics, logs, and traces are complementary

A monitoring system should explain the three pillars clearly. Metrics are compact numerical time series that answer what changed and when. Logs are detailed event records that explain why a specific error happened. Traces connect work across services and show where latency or errors occurred in a distributed request.

The platform should not treat them as interchangeable. Metrics power alerting, dashboards, and SLO burn-rate calculations because they are cheap to aggregate. Logs support debugging and audit trails, but they are more expensive to index and query. Traces provide request-level causality, but sampling is usually required. Correlation fields such as trace ID, service, region, deploy version, customer tier, and timestamp let users move from an alert to the relevant logs and traces quickly.

Time-series ingestion, rollups, and cardinality

The time-series store is optimized around tenant, metric name, tag set, and time bucket. Compression works well when samples for the same series arrive in order and have similar timestamps or values. Rollups at 1 minute, 5 minutes, 1 hour, and 1 day resolutions keep long-range dashboards affordable.

The biggest operational risk is cardinality explosion. A label such as request_id, user_id, session_id, or raw URL can create millions of unique series and make both storage and queries fail. The ingestion gateway and processors should enforce label allow lists, drop unbounded labels, limit unique series per tenant, and surface cardinality reports so customers can fix instrumentation.

Alert rule evaluation over time-series windows

Alert rules should evaluate on stable, bounded windows instead of querying arbitrary raw data every second. A threshold rule might evaluate the last 5 minutes every 1 minute. A burn-rate rule might evaluate both 5-minute and 1-hour windows to catch fast outages without paging on tiny blips.

Rule workers should shard by tenant and rule ID, read rollup chunks, apply no-data semantics, and write an idempotent evaluation result. For counters, the engine must handle resets. For percentiles, it should use histogram summaries or sketches rather than averaging p95 values incorrectly. Late data should be either ignored after a grace period or handled through explicit re-evaluation policies.

Deduplication, grouping, silencing, and escalation

Paging one person for every matching time series is a common failure mode. The system should compute an incident fingerprint from tenant, rule, service, environment, region, and chosen group labels. Repeated firings update the same incident with dedupe_count and last_fired_at rather than creating a new page every minute.

Grouping collapses related alerts into one incident view. Silences and maintenance windows suppress known work. Escalation policies decide when to page primary on-call, secondary on-call, managers, or a customer webhook. Recovery windows prevent flapping by requiring the condition to remain healthy for several evaluations before resolving.

SLOs, SLIs, and error budgets

An SLI is a measured reliability signal such as successful requests divided by total requests, p99 latency under a threshold, or synthetic checkout success rate. An SLO is the target for that SLI over a window, such as 99.9 percent success over 30 days. The error budget is the allowed badness left before the team violates the SLO.

The monitoring system should compute SLO windows from metrics and synthetic checks, show remaining budget, and alert on burn rate instead of only absolute error count. Multi-window burn-rate alerts reduce noise by paging when the service is burning budget both quickly and consistently.

Logs, traces, sampling, and cost control

Logs and traces can dwarf metric volume. The system should encourage structured logs, field redaction, per-tenant quotas, dynamic sampling, and retention tiers. High-value error traces can be kept at a higher rate than routine successful traces.

Tail sampling can keep traces with errors, high latency, or rare routes after seeing the full request. Head sampling is cheaper and simpler but may drop the one trace needed during an incident. A premium design lets teams configure sampling by service, route, status, tenant tier, and incident mode.

Scaling

Prototype: one region and managed stores

Start with OpenTelemetry collectors, a managed queue, a managed time-series database, a search service for logs, and a relational database for alert rules and incidents. Evaluate rules every minute and send notifications through one provider. This proves the product workflow without building every storage engine.

Growth: partition by tenant and telemetry type

Split ingestion topics by tenant tier and telemetry type. Add per-tenant quotas, metric rollups, query caching, log retention tiers, and alert scheduler shards. Keep dashboards and alerting separate so expensive investigations do not delay paging.

Large scale: custom TSDB and distributed alert engine

Move high-volume metrics into a horizontally sharded time-series store. Partition by tenant, metric, series hash, and time. Run alert workers as a distributed scheduler with leases, idempotent evaluations, and durable alert state. Use object storage for older logs and traces.

Multi-tenant SaaS scale: isolation and cost controls

Introduce dedicated ingestion lanes for enterprise tenants, quota-aware query schedulers, cardinality analysis, storage tiering, sampled traces, and customer-visible usage reports. Add regional data residency options and stronger RBAC for regulated customers.

Global scale: regional ingestion and replicated control plane

Ingest telemetry in the nearest region, keep alerting local for low latency, and replicate rule definitions, silences, dashboards, and incidents through a control plane. Global dashboards can aggregate rollups asynchronously while regional alerts continue during cross-region failures.

Bottlenecks & Optimizations

High-cardinality metric labels

Reject or down-rank labels such as request ID, user ID, session ID, and raw URL before they create unbounded series. Enforce tenant cardinality quotas, provide label usage reports, and move high-cardinality debugging data into logs or traces instead of metrics.

Alert evaluation scans too much raw data

Evaluate rules from precomputed rollups and histogram sketches. Shard rules by tenant and rule ID, cache query plans, limit lookback windows, and precompute SLO burn rates for popular services.

Incident storms and alert fatigue

Group alerts by service, region, and severity; deduplicate by fingerprint; enforce recovery windows; add maintenance silences; and route warnings to tickets or chat while reserving pages for user-impacting symptoms.

Log and trace storage explosion

Use structured logging, indexing allow lists, compression, object storage, sampling, retention tiers, and dynamic incident-mode sampling. Do not index every arbitrary field by default.

Expensive dashboard queries

Use rollups, query result caching, panel-level timeouts, progressive loading, and resolution selection based on time range. Limit ad hoc high-cardinality group-bys and surface partial results instead of blocking the whole dashboard.

Hot tenants during major incidents

Isolate ingestion and query capacity by tenant tier, apply fair scheduling, reserve alerting capacity, and allow non-critical telemetry to be sampled or delayed while critical SLI metrics continue to flow.

Failure Handling

Agent or collector cannot reach the service

Agents buffer locally within disk limits, retry with exponential backoff, and expose self-monitoring metrics. When buffers fill, drop low-priority logs or traces before dropping critical health metrics, and mark gaps clearly in dashboards.

Telemetry bus lag grows

Autoscale consumers, shed non-critical telemetry, increase sampling, and prioritize metric and alert-relevant streams over bulk logs. Alert operators on ingestion freshness so teams know when dashboards may be stale.

Time-series store shard is unavailable

Route reads to replicas when possible, serve partial dashboard results with clear warnings, and keep alert rules from paging on missing data unless the rule explicitly treats no data as bad. Replay queued samples after recovery.

Alert engine workers fail

Use scheduler leases so another worker can claim rules after a timeout. Store evaluation checkpoints and incident fingerprints durably so retries are idempotent and do not create duplicate notifications.

Notification provider is down

Retry with backoff, fail over to secondary channels, escalate through alternate providers, and show delivery status on incidents. The alert state should remain active even if a downstream paging integration is temporarily unavailable.

Bad alert rule causes a storm

Apply per-rule and per-route notification rate limits, automatic grouping, circuit breakers, and emergency tenant-wide silences. Keep audit logs so teams can identify who changed the rule and roll it back.

Regional outage affects ingestion

Agents should fail over to another regional ingestion endpoint when policy allows. Control-plane data such as rules and silences should replicate across regions, while regional alert engines continue evaluating the telemetry they can still receive.

Security

Tenant isolation

Every sample, log, span, rule, dashboard, and incident must carry a tenant boundary. Enforce tenant IDs in storage partition keys, authorization checks, query planning, cache keys, and notification routing.

Ingestion authentication

Agents and collectors should use scoped ingestion tokens or mutual TLS. Rotate tokens, bind them to tenants and environments, and reject telemetry that attempts to spoof another tenant or reserved system labels.

PII and secret protection

Logs and spans often contain customer data, tokens, emails, or payment fragments. Redact at the agent when possible, apply server-side detectors, support field-level retention policies, and prevent sensitive fields from being indexed broadly.

RBAC and auditability

Limit who can view production telemetry, modify alert routes, silence incidents, or change SLO definitions. Record audit events for rule edits, silence creation, escalation changes, dashboard sharing, and token rotation.

Encryption and retention controls

Encrypt telemetry in transit and at rest. Support customer-defined retention, legal hold where required, deletion workflows, and data residency controls for regulated tenants.

Abuse and cost controls

Protect public ingestion endpoints from token abuse, replay storms, and deliberate cardinality attacks. Apply quotas, anomaly detection on ingestion patterns, and emergency disablement of compromised tokens.

Tradeoffs

Pros

  • +Separating metrics, logs, and traces lets each storage engine match its access pattern.
  • +Asynchronous ingestion through a queue absorbs bursts and protects downstream stores.
  • +Rollups make dashboards and alert evaluation predictable at scale.
  • +Durable alert state enables deduplication, grouping, silencing, and escalation without duplicate pages.
  • +SLO and burn-rate alerts focus teams on user impact rather than raw symptom noise.

Cons

  • Multiple storage systems increase operational complexity and consistency challenges.
  • Sampling and retention policies can drop the exact log or trace needed for a rare incident.
  • Strict cardinality limits can surprise customers if instrumentation is not explained well.
  • Alert grouping reduces noise but can hide distinct root causes if fingerprints are too broad.
  • Global multi-region ingestion and data residency requirements complicate rule replication and query planning.

Alternatives

Alternative one is a metrics-only monitoring system. It is simpler and cheaper, and it may be enough for infrastructure health, but it cannot provide full incident investigation because logs, traces, SLO context, and notification workflows are missing.

Alternative two is a log-first observability system that stores all telemetry as events in a search engine. It gives flexible debugging, but metric alerting and long-range dashboards become expensive unless rollups and specialized time-series indexes are added.

Alternative three is to rely on separate best-of-breed tools for metrics, logs, tracing, paging, and dashboards. This reduces platform scope but weakens correlation, ownership, consistent RBAC, and alert fatigue controls.

When not to use this design

Do not build a full Datadog-style platform for a small application with a few services and modest reliability needs. Managed monitoring, cloud provider metrics, and a simple paging integration are usually enough until telemetry volume, cross-service debugging, compliance, or alert fatigue justify the complexity.

Follow-up Questions

How is this different from a metrics collection system?

A metrics collection system focuses on scraping, receiving, storing, and querying numerical time series. A monitoring system consumes those metrics and combines them with logs, traces, health checks, dashboards, alert evaluation, deduplication, silencing, notification routing, SLOs, and incident workflows.

How do you reduce alert fatigue?

Alert on symptoms and SLO burn rates instead of every internal cause. Group related firings, deduplicate by fingerprint, add recovery windows, route warnings to tickets, silence maintenance, suppress known dependencies, and review noisy alerts with ownership and metrics.

What happens when telemetry arrives late?

Define a grace period per telemetry type. Dashboards can backfill late samples, but alert evaluation should use stable windows and avoid re-paging old incidents unless policy requires it. Late data can update history and SLO reports without rewriting already-delivered notifications.

How should high-cardinality labels be handled?

Block or drop unbounded labels at ingestion, enforce tenant series quotas, keep allow lists for indexed dimensions, and guide users toward logs or traces for per-request identifiers. Also provide cardinality dashboards so teams can fix instrumentation before it becomes an outage.

How do you design SLO burn-rate alerts?

Compute an SLI such as good requests divided by total requests, compare it with the SLO target, and calculate how quickly the error budget is being consumed. Use multi-window alerts, for example a short window plus a longer window, to page on sustained user impact while filtering transient spikes.

How do you ensure alert evaluation is reliable?

Shard rules deterministically, use leases, write idempotent evaluation results, read from rollups, persist incident fingerprints, and monitor the monitoring system itself. Critical rule evaluation should have reserved capacity and should not depend on expensive dashboard queries.

How do logs and traces connect to a metric alert?

Use shared labels and correlation IDs. A metric alert includes tenant, service, environment, region, deploy version, and time window. The UI uses those fields to pre-filter logs and traces, then trace IDs link individual logs to request waterfalls.

Company Variations

Amazon

Amazon interviewers may emphasize CloudWatch-like scale, multi-tenant quotas, DynamoDB or S3-backed storage, operational alarms, cost controls, and keeping alerting alive during regional failures. Be ready to explain partition keys and noisy-neighbor isolation.

Microsoft

Microsoft may frame this around Azure Monitor, enterprise tenants, RBAC, audit logs, data residency, Teams integration, and hybrid cloud agents. Discuss control-plane durability, customer-managed retention, and strict tenant isolation.

Netflix

Netflix often cares about large-scale service health, streaming reliability, adaptive alerting, chaos testing, and reducing pages from cascading failures. Emphasize SLOs, regional dashboards, trace sampling, and alert grouping by customer-impacting symptoms.

Google

Google may push on SRE concepts: SLIs, SLOs, error budgets, burn-rate alerts, Borg-style fleet scale, and the difference between symptoms and causes. Be precise about multi-window alerting and avoiding pages for non-actionable noise.

LinkedIn

LinkedIn may tie the design to large microservice graphs, member-facing reliability, Kafka-based pipelines, and on-call ownership across many teams. Discuss service dependency mapping, tenant-like product isolation, and incident collaboration workflows.

Interview Tips

Start by saying this is an observability and alerting platform, not just a metric scraper. Draw telemetry ingestion first, then split into metric storage, log and trace storage, query APIs, alert evaluation, alert state, and notification routing.

When discussing tradeoffs, keep tying decisions back to human outcomes: fast detection, useful context, fewer noisy pages, and reliable escalation. Interviewers reward candidates who understand that the hardest part of monitoring is turning huge telemetry volume into a small number of actionable incidents.

What interviewers expect

  • Clearly separate collection, ingestion, storage, query, alerting, and notification routing.
  • Explain why metrics, logs, and traces use different storage and retention strategies.
  • Use rollups and stable evaluation windows for alert rules.
  • Discuss SLOs, SLIs, error budgets, and burn-rate alerts.
  • Show how deduplication, grouping, and silencing reduce alert fatigue.
  • Cover failures of the monitoring system itself, especially alerting and notifications.

Common mistakes

  • !Designing only metric scraping and forgetting logs, traces, dashboards, SLOs, deduplication, and paging.
  • !Letting alert rules scan raw telemetry instead of using bounded windows and rollups.
  • !Ignoring cardinality limits until one label creates millions of series.
  • !Paging on every low-level cause instead of user-impacting symptoms and burn rates.
  • !Treating notification delivery as fire-and-forget without retries, escalation, and delivery state.
  • !Assuming logs, metrics, and traces belong in one generic database.

Red flags

  • ×No concrete capacity math for samples per second, storage per day, or rule evaluations.
  • ×No distinction between ingestion freshness, query latency, and alert detection latency.
  • ×No plan for alert grouping, silencing, maintenance windows, or flapping control.
  • ×No tenant isolation or quota model for a multi-tenant observability platform.
  • ×No answer for high-cardinality labels, trace sampling, or log retention cost.

Revision Notes

  • A full monitoring system ties together metrics, logs, traces, synthetic checks, dashboards, alerting, notification routing, SLOs, and incident history.
  • It consumes metrics collection rather than stopping there. The domain crux is alert evaluation, correlation, deduplication, silencing, escalation, and reducing alert fatigue.
  • Metrics are compact time series for alerting and dashboards. Logs provide detailed event context. Traces show distributed request causality.
  • Use asynchronous ingestion through a durable telemetry bus so agents and gateways are decoupled from storage and indexing.
  • Use a time-series store with compressed chunks, rollups, and retention tiers for metrics. Use object storage plus search indexes for logs and traces.
  • Control metric cardinality aggressively. Unbounded labels such as user IDs, request IDs, raw URLs, and session IDs can break ingestion and queries.
  • Alert rules should evaluate from rollups over stable windows. Avoid raw scans in the paging path.
  • Deduplicate by incident fingerprint, group related firings, respect silences, and use recovery windows to avoid flapping.
  • Notification routing needs escalation policies, retries, delivery tracking, and integrations with PagerDuty-style systems, chat, email, SMS, tickets, and webhooks.
  • SLOs use SLIs and error budgets. Burn-rate alerts page when the service is consuming budget too quickly and consistently.
  • The monitoring system must monitor itself: ingestion lag, alert evaluation lag, dropped telemetry, notification failures, and query latency are all first-class signals.

Flashcards

Quiz

0/7 answered

  1. 1.What is the best description of this monitoring system's scope?

  2. 2.Why should alert rules usually evaluate over rollups instead of raw samples?

  3. 3.Which label is most likely to cause high-cardinality problems if used on every metric?

  4. 4.What does alert deduplication primarily prevent?

  5. 5.What is a good default strategy for logs and traces at high volume?

  6. 6.What is the purpose of SLO burn-rate alerting?

  7. 7.During a notification provider outage, what should the monitoring system do?

Cheat Sheet

Goal: build an observability and alerting platform that connects metrics, logs, traces, synthetic checks, dashboards, SLOs, incidents, and notification escalation.

Workload: with 100,000 monitored resources and 200 active metric series each, expect about 20M active series and 2M metric samples per second. Logs at 1 KB per second per resource are about 100 MB per second. Sampled traces at 500K spans per second are another high-volume stream.

Ingestion: agents and collectors batch telemetry, gateways authenticate and enforce quotas, and a durable telemetry bus decouples ingestion from processing.

Storage: metrics go to a time-series store with compressed chunks and rollups. Logs and traces go to object storage plus search indexes. Alert rules, silences, routes, SLOs, and incidents go to a durable control-plane store.

Query: dashboards should use rollups, caching, timeouts, and progressive loading. Correlate telemetry using service, environment, region, deploy, timestamp, trace ID, and request ID.

Alerting: evaluate rules on stable windows from rollups. Handle no-data semantics, counter resets, late data, and idempotent retries.

Noise control: deduplicate by fingerprint, group related firings, silence maintenance, use recovery windows, and route only actionable severity to human pages.

SLOs: define SLIs, SLO targets, and error budgets. Use multi-window burn-rate alerts to page on sustained user impact.

Failures: monitor ingestion lag, processor lag, alert evaluation lag, dropped telemetry, query latency, notification delivery, and the monitoring system's own health.

Security: enforce tenant isolation, scoped ingestion tokens, RBAC, audit logs, encryption, retention controls, redaction, and cost protection against cardinality attacks.

References