Monitoring whether a system is up and running is not the same as understanding why it behaves the way it does — and confusing these two things is the most expensive mistake engineering teams make when scaling a distributed architecture. A green dashboard does not mean the user is having a good experience. It just means that the services respond to pings. The distance between these two statements is exactly where the hardest-to-find bugs, silent degradations, and incidents that take hours to diagnose live.
What separates monitoring from observability
Monitoring starts from questions known in advance: is the server responding? Is the queue growing? Did the error rate exceed the threshold? You define the metrics, configure the alerts, and wait for something to cross a threshold. It works well when the system is simple and failure modes are predictable.
Observability is different. The term, borrowed from control theory, describes the ability to infer the internal state of a system from its outputs. In practice, it means being able to answer questions you didn't know you would ask when you built the system. Why does this specific user get 503 while the others don't? Why did checkout latency increase by 40% just for customers in São Paulo? Why does this service consume twice as much CPU on Tuesdays after 2pm?
These questions do not have preconfigured alerts. They require rich, correlated data with enough context to guide a real investigation.
Why logs alone don't solve
For years, the standard answer to "how to debug in production" was "add more logs". Logs are useful — record discrete events, capture error messages, allow auditing. But in distributed architectures, they become insufficient for structural reasons.
A request that passes through ten services generates logs in ten different places. Without a correlation identifier correctly propagated throughout the chain, it is impossible to reconstruct the path that request took. Even with correlation IDs, you're pulling together scattered fragments of text and trying to piece together a coherent narrative manually. The time this takes in an active incident is time the user spends without service.
Metrics solve part of the problem — they show aggregate trends and enable quick alerts — but they lose context by design. You know that the average latency has gone up, but you don't know which specific operation, which database, which external call was responsible.
Traces close this gap. A trace follows a request from start to finish, going through each service, each bank call, each external integration, recording duration and attributes at each step. With traces, the investigation that would take hours of grep in log files now takes minutes of visual analysis of the time spent by each span.
The problem that OpenTelemetry came to solve
Before OpenTelemetry, instrumenting a system for observability meant choosing a vendor—Datadog, New Relic, Jaeger, Zipkin—and implementing each one's proprietary SDK. Switching vendors meant rewriting instrumentation across the entire codebase. Using multiple tools simultaneously meant maintaining multiple SDKs, with different semantics and duplicated overhead.
OpenTelemetry, a CNCF graduate project with contributions from Google, Microsoft, Splunk and dozens of other organizations, ended this model in two ways. First, it defined a unified specification for the three pillars — metrics, logs and traces — with consistent semantics between them. Second, it implemented this specification in SDKs for virtually all relevant languages, with self-instrumentation for the most common frameworks.
The practical result is that the instrumentation is in the code once, and the data destination is configured in the collector. You can send traces to Jaeger during development, to Tempo in production, and test Honeycomb in parallel, all without touching a line of application code. Supplier lock-in no longer exists as a technical constraint.
How to implement without stopping the team
The common pitfall when adopting OpenTelemetry is trying to instrument everything at once. The intelligent path is incremental, starting with the points of greatest diagnostic value.
The first step is to install the SDK and enable self-instrumentation for the HTTP framework that the service uses. In Node.js, Go, Python, and Java, this automatically covers inbound calls, outbound calls, and database connections without any modifications to the business code. You will have traces with useful context in less than an hour of work.
The second step is to configure the OpenTelemetry Collector as an intermediary between the applications and the observability backends. The Collector receives data, can transform it, filter it and send it to multiple destinations. This decouples the application from any decision about where the data is stored.
The third step, which most teams underestimate, is defining an attribute strategy. Traces without contextual attributes — user ID, tenant ID, deployment version, region — are difficult to filter when you are looking for a specific pattern. Standardizing the attributes that every service must propagate is an architectural decision, not an implementation one.
What changes in the debug process in production
With real observability implemented, the dynamics of incident investigation change in concrete ways. Instead of starting an incident by consulting infrastructure dashboards and trying to correlate CPU alerts with latency spikes, the team starts with the affected user experience.
A trace from the user who reported the problem shows exactly where the latency was concentrated, which service returned an error, which bank query took three times longer than normal. The hypothesis is born from the data, not from assumptions about what could have changed.
This shortens the distance between "something is wrong" and "here's the root cause and responsible line of code". Teams operating with mature observability arrive at postmortems with evidence, not rough reconstructions based on fragmented logs.
The change is not just technical. Teams that develop the discipline of instrumenting well and actively using traces during development — not just during incidents — accumulate an understanding of the system that no architecture document can replace. Observability, when taken seriously, becomes a continuous learning tool about how software behaves in the real world.
Also read
- Observability in Distributed Systems: Logs, Metrics and Tracing
- Observability with OpenTelemetry: Metrics, Logs and Distributed Tracing
- Workers: debugging, logs and Workers Tail — observability at the edge without a log server
- Serverless for applications: architecture in everyday life
- Cloudflare Workers in production: what changes after hello world
- AI in medical diagnosis: what changes in practice for healthcare systems
