Module 12 · Microservices patterns · Lesson 8 of 8
Service mesh
A dedicated infrastructure layer for service-to-service traffic: a proxy beside every service and a control plane that configures them all. What the mesh provides (mTLS, retries, timeouts, traffic shifting, telemetry), what it costs.
Why it matters
The previous lessons each solved one problem: discovery, breakers, bulkheads, sidecars. A service mesh bundles them into a platform: every service gets mutual TLS, retries with budgets, timeouts, circuit breaking, canary routing and uniform telemetry without changing a line of application code. For a fleet of hundreds of services in several languages that is transformative. For a dozen services it is a heavy dependency that solves problems you may not have. Knowing the threshold is the design judgement interviewers look for.
The idea
A service mesh has two parts. The data plane is a proxy (almost always Envoy or a purpose-built equivalent) deployed with every service instance, intercepting all inbound and outbound traffic. The control plane (Istio's istiod, Linkerd's control plane, Consul) holds the desired configuration, issues certificates, and pushes routing, security and resilience policy to every proxy. Application code sends plain requests to a service name; the mesh does the rest.
What the mesh provides
| Capability | What you get | Without a mesh |
|---|---|---|
| Security | Mutual TLS between every pair of services with automatic certificate rotation; service identity; authorization policy (A may call B's /orders only) | Per-language TLS code, manual certificate management, network-level rules |
| Resilience | Timeouts, retries with budgets, circuit breaking and outlier ejection, configured centrally per route | Libraries per language, inconsistently applied |
| Traffic management | Weighted routing for canaries, header-based routing, mirroring (shadow traffic), fault injection for chaos tests | Gateway-level only, or custom code |
| Observability | Uniform request metrics (rate, errors, latency per service pair), access logs and distributed trace spans | Instrument every service by hand |
| Discovery and balancing | Built in, with zone-aware and least-request balancing | Platform DNS plus client libraries |
What it costs
Resources: a proxy per instance, typically 50 to 150 MB of memory and some CPU, which across thousands of pods is a meaningful fraction of the cluster. Latency: one proxy hop on each side of a call, usually under a millisecond each, visible at the tail. Complexity: a new control plane to run, upgrade and debug, with its own failure modes (a bad config push affects every service at once), plus a learning curve around its configuration model. Debugging: a connection problem may now be in the application, the proxy, the control plane or the policy. The mesh is infrastructure that needs an owning team.
Sidecar versus sidecarless
The sidecar model gives each instance its own proxy with full isolation. Sidecarless or ambient designs (Istio ambient, Cilium with eBPF) move layer-4 functions (mTLS, telemetry) into a per-node agent and add a per-namespace layer-7 proxy only where HTTP policy is needed, cutting resource overhead substantially and simplifying pod lifecycles. The trade is less per-workload isolation and a newer, less battle-tested architecture. The direction of the ecosystem is toward reducing the per-pod cost.
When it is worth it
Adopt a mesh when you have dozens to hundreds of services in several languages, a compliance requirement for encryption in transit everywhere, a need for uniform telemetry and policy that libraries cannot deliver consistently, or an existing platform team to own it. Do not adopt it for a dozen services in one language: a shared library plus a gateway covers resilience and discovery, and mTLS can wait until it is required. A mesh adopted before its problems exist is a complexity tax paid for a benefit not yet needed.
Operating one
Roll it out namespace by namespace with permissive mTLS first, then strict. Treat control-plane configuration as code with review and staged rollout, because a mistake is cluster-wide. Monitor proxy resource usage and the control plane's push latency. Keep the mesh version current; the ecosystem moves fast and old versions accumulate known issues. Use the mesh's fault injection to run resilience tests, which is one of its underrated benefits.