Skip to content
Incident LabOpenTelemetry

Production

Production architecture

This lab is not a production observability platform. Here is what a real one adds, and why.

From one laptop to production

This lab runs one Collector and single-binary backends on a laptop. The concepts are the same in production; the shape is not. A typical layout has two tiers of Collectors:

Output
 Application  ── OTel SDK (traces, metrics, logs)
     │  OTLP over localhost or the node network
     ▼
 Collector AGENT    one per host or node (Kubernetes DaemonSet) or a sidecar
     │  adds host and Kubernetes metadata, batches, applies cheap filters
     │  OTLP with TLS
     ▼
 Collector GATEWAY  a horizontally scaled pool behind a load balancer
     │  central policy: tail sampling, redaction, routing, rate limits, auth
     ▼
 Observability backends   traces · metrics · logs (self-hosted or a vendor)

Agent vs gateway

AgentGateway
RunsNext to the workload (per node or sidecar)As a shared, scaled service
Good forLocal enrichment (k8sattributes, host metrics), fast hand-off so apps never blockPolicy in one place, tail sampling, routing to several backends, holding credentials
Failure scopeOne nodeEverything, so it must be highly available
Tail samplingNo: it sees only part of each traceYes, if every span of a trace reaches the same instance (a loadbalancing exporter routes by trace id)

What changes

ConcernWorkshopProduction
CollectorsOne containerAgents plus a highly available gateway pool
Batchingbatch processor, 2 sBatching plus persistent queues sized from measured throughput
Retries and queuesExporter defaults, in memorysending_queue with a file storage extension so a restart does not lose data; bounded retries
Backpressurememory_limitermemory_limiter, plus autoscaling and alerts on refused data
Transport securityPlain OTLP on a private networkTLS everywhere, mTLS between tiers
AuthenticationNoneAuthenticated receivers, per-tenant credentials, secrets from a vault
Network boundaries127.0.0.1 portsPrivate networks, egress allow-lists, no public receivers
BackendsSingle binaries, local diskDistributed deployments on object storage, replicated
Retention72 hoursPer signal and per tenant: raw traces for days, metrics for months
SamplingKeep everythingHead sampling in SDKs, tail sampling at the gateway for errors and slow requests
CardinalitySmall and controlledLimits in the backend, label allow-lists, dropping in the Collector
AlertingNoneSLO burn-rate alerts on RED metrics and saturation
Access controlAnonymous GrafanaSSO, roles, per-team data access
CostYour laptopA budget: volume, retention and cardinality are engineering decisions
The Collector itselfNot monitoredMonitored: accepted, refused, dropped and queue-size metrics

Sampling in production

Keeping every trace is rarely affordable at scale. Two families of sampling:

  • Head sampling decides when a trace starts, in the SDK (for example a ParentBased(TraceIdRatioBased(0.1)) sampler keeps 10% and makes downstream services follow the caller's decision). Cheap, but it decides before anyone knows whether the request will fail.
  • Tail sampling decides once the trace is complete, in a gateway Collector with the tail_sampling processor. It can keep every error and every slow trace plus a small share of the rest. It costs memory (whole traces are buffered) and needs trace-aware load balancing.

Most teams combine them, and keep metrics unsampled: metrics are aggregated in the SDK, so their cost does not grow with traffic the way spans do. When traces are sampled, dashboards built from spans must account for it; RED metrics from the SDK do not have that problem.

Alerting on what users feel

Alert on symptoms, not causes: a burn rate on the checkout SLO, error ratio, p99 latency. Use traces and logs to find the cause once an alert fires, which is exactly what the Incident Lab practises. Alerting on every CPU spike and every ERROR log line produces noise that teaches people to ignore pages.

Before you copy anything from this repository

The lab is deliberately simple and deliberately open. Before reusing a piece of it, add TLS and authentication, remove anonymous access, replace the demo credentials, set real resource limits, decide retention, and monitor the Collector. See the Security page.