What problem does a service mesh (Istio/Linkerd) actually solve that you couldn't already do in application code?
Istio and Linkerd don't invent new capabilities — they move mTLS, retries, and observability out of every service's code and into shared, centrally governed infrastructure.
LEARN BY DOINGPut your intuition to work3 steps
What problem does a service mesh (Istio/Linkerd) actually solve that you couldn't already do in application code?
Use the lesson’s examples and explanation to check your idea.
Personal reflection. Nothing is sent to an AI service.#Everything a mesh does, you could write yourself
That's the uncomfortable truth interviewers are probing for. Mutual TLS between services, retries with backoff, timeouts, circuit breakers, weighted traffic splitting for canaries, and per-route latency dashboards are all things you can implement with application-level libraries — resilience4j, gRPC interceptors, a hand-rolled certificate rotation job. Netflix ran a massive, successful microservices fleet for years on exactly that: Eureka, Ribbon, and Hystrix as JVM libraries. So if none of this is technically new, what does a service mesh actually buy you?
#The problem is not the feature list, it's who owns it
In the library-per-service model, every one of these cross-cutting concerns lives inside application code, which means every team, in every language, has to adopt the library, configure it correctly, and keep it upgraded. A Python service and a Go service and a Java service each need their own retry library, their own certificate handling, their own tracing instrumentation — and they will drift. One team pins an old version with a known bug. Another team never wires up mTLS because "it's on the roadmap." A retry policy change means coordinating a rollout across forty repositories instead of editing one config.
A service mesh moves all of this out of the application process and into a sidecar proxy — a lightweight proxy (Envoy, in Istio's case; Linkerd ships its own minimal proxy) deployed alongside every service instance, usually as a second container in the same Kubernetes pod. Every byte of inbound and outbound traffic for that service is transparently redirected through its sidecar. The application still just makes a plain HTTP or gRPC call to localhost — it has no idea a proxy is involved.
#Control plane and data plane
The sidecars are the data plane — they do the actual work of intercepting, encrypting, retrying, and routing traffic. A control plane (istiod in Istio, the equivalent in Linkerd) is a separate set of components that computes the desired configuration — routing rules, TLS certificates, retry policies — and pushes it down to every sidecar. Changing a retry policy or rolling out a canary now means updating one resource in the control plane; every sidecar in the mesh picks it up without a single application redeploy, in any language.
#What "you couldn't do in application code" actually means
You could do every individual piece in application code. What you couldn't easily do is make it uniform, polyglot, and centrally governed without every team re-implementing and re-certifying the same behavior. A mesh gives every workload a cryptographic identity (commonly following the SPIFFE standard), issues and rotates short-lived certificates automatically, and enforces mutual TLS between services without a single line of certificate-handling code in any service. It gives you a live topology graph and consistent golden-signal dashboards (latency, traffic, errors, saturation) for every service the moment it joins the mesh, generated from proxy telemetry rather than each team's own instrumentation choices. And it lets a platform team enforce an authorization policy — "only the checkout service may call the payments service" — as infrastructure configuration, independent of what any individual service's code does or doesn't check.
#What it costs you
None of this is free. Every call now makes two extra hops — client sidecar, then server sidecar — adding real latency, typically single-digit milliseconds per hop but it adds up across a deep call chain. Every pod carries an extra container consuming CPU and memory, multiplied across your whole fleet. The control plane itself is another distributed system you now operate, upgrade, and debug, and a bug or misconfiguration there can affect every service at once. Tracing a problem now involves reasoning about proxies you didn't write, which is a real cost when something goes wrong at 2am. For a platform running fewer than a dozen or two services, the operational overhead of running a mesh routinely exceeds the value it delivers — the same resilience behaviors are often cheaper to hand-roll with a shared library at that scale.
#When the trade actually pays off
The case for a mesh gets stronger as the number of services and the number of languages both grow, and stronger still when a platform team needs to enforce a security or traffic policy consistently without depending on every application team to implement it correctly. If you're running a handful of services in one language with one team, a mesh is usually solving a problem you don't have yet.