A service mesh deploys a lightweight proxy (a sidecar) alongside every service instance, and routes all inter-service traffic through these proxies instead of directly between application processes. That gives you consistent retries, timeouts, mutual TLS, load balancing, and observability across every service in the mesh — configured centrally, uniformly — without changing a line of any individual service’s code.
Worked example: moves service-to-service concerns (mTLS, retries, timeouts, traffic-splitting, telemetry) out of app code into a sidecar proxy (Envoy) beside every service, run by a central control plane (Istio, Linkerd). Gotcha: it adds a network hop and proxy overhead per call plus real operational complexity; for a handful of services it is rarely worth it — a library or the platform layer is simpler until you have enough services that per-app implementation is the bigger cost.