Automated tests answer an important question: does the software behave correctly in the scenarios we described? Production answers a different question: does it behave correctly across the data, timing, infrastructure, and user behavior that actually exist?
I think of observability as continuous testing. Not as a replacement for unit and integration tests, but as the continuation of the test process after deployment. Real users execute paths we did not imagine, thousands of times, and a good observability system lets us inspect the outcomes.
Tests validate a model of reality
Every pre-production test is a model. We choose inputs, isolate dependencies, control time, and assert the outcome we expect. That control is exactly what makes tests fast and useful. It also defines their boundary.
End-to-end suites widen the boundary, but they often become expensive simulations: difficult to author, slow to run, and sensitive to unrelated changes. They still use synthetic users, known fixtures, and a fraction of production’s concurrency and topology.
Fast, isolated, deterministic.
Contracts, persistence, and dependency behavior.
Real data, traffic, timing, and infrastructure.
Make a release a testable hypothesis
“Deploy and watch the dashboard” is not continuous testing. The release needs an explicit claim before it ships. For example: this change should reduce reconnect failures without increasing call setup time.
That claim produces two kinds of measurements:
- Success metrics describe the outcome the change is supposed to improve.
- Guardrails describe the things that must remain healthy while pursuing that outcome.
Instrumentation should also identify the release, experiment, region, browser, device class, and other dimensions needed to explain a difference. Without release identity and useful context, production metrics describe the fleet but cannot evaluate the change.
The continuous testing loop
- 1State the hypothesis
What should improve, and what must not regress?
- 2Instrument the behavior
Emit outcomes, context, and release identity.
- 3Expose a cohort
Start small and preserve a meaningful comparison group.
- 4Compare outcomes
Read success metrics, guardrails, traces, and logs together.
- 5Decide and learn
Expand, rollback, or revise the model behind the change.
Cohorts make production evidence useful
An aggregate can hide a regression. If ten percent of traffic receives a new version, a severe problem in that cohort may look like a small movement in the fleet-wide average. Compare like with like instead.
Cohorts can be defined by version, feature flag, tenant, region, or another stable assignment. The important properties are that the comparison is intentional, attribution is reliable, and the sample is large enough to support a decision.
Metrics tell you where; traces and logs tell you why
Metrics are ideal for evaluating population-level outcomes. They show whether a cohort changed and which dimensions concentrate the effect. Once a suspicious cohort is known, traces connect the request path and logs provide the local details needed to explain it.
This suggests an investigation order: detect with metrics, narrow with dimensions, inspect representative traces, then use targeted logs. Starting with unstructured logs asks an engineer to discover both the population and the mechanism at the same time.
An example: changing a reconnect path
Imagine changing how a real-time client reconnects after losing its server connection. A unit test can verify the retry state machine. An integration test can verify that the client obtains a new endpoint and establishes a session. Neither proves that reconnections become less disruptive under real networks and real traffic.
- Successful reconnections within an acceptable time window.
- Setup latency before and after the change.
- Repeated retries and sessions abandoned during recovery.
- Differences by browser, region, and network quality.
- Differences between clients using the new path and a stable control cohort.
Unit tests establish that state transitions are correct. Integration tests establish that the client and server agree on the protocol. Cohort metrics establish whether the protocol improves recovery under real traffic.
Where this approach can lie
Production evidence is not automatically truth. A metric may measure a proxy rather than the user outcome. Successful requests can exclude users who abandoned early. A global average can dilute a regional failure. A short observation window can miss delayed effects.
- Define who can disappear from the denominator.
- Track failures that occur before normal telemetry initializes.
- Segment by dimensions implied by the architecture.
- Choose an observation window that covers the feature lifecycle.
- Preserve qualitative reports as evidence, not dashboard noise.
What should remain pre-production
Production should never be the first line of defense for destructive migrations, authorization boundaries, privacy controls, financial calculations, or invariants that can be checked cheaply and deterministically. Observability is strongest where reality has more combinations than a test environment can reproduce, not where failure would be irreversible.
The practical goal is a layered confidence system. Unit and integration tests protect known behavior before release. Progressive delivery limits exposure. Cohort metrics, traces, and logs continuously test our assumptions against reality. Each layer catches a different class of mistake.