When to reach for it
- You have a fleet of services in multiple languages and you're tired of porting the same auth / mTLS / retry / observability code into each runtime
- You need to add a capability (mTLS, distributed tracing, secrets injection) to existing services you can't modify
- A platform team owns the cross-cutting concern and shouldn't need a PR into every app to roll out a change
- The capability has its own release cadence and shouldn't be coupled to your app's deployment
What it actually costs
Every pod runs two processes — double the memory floor, double the things that can OOM, double the patch surface. Local debugging gets weirder because traffic goes through a proxy you didn't write. Latency goes up 1–3 ms per hop, which doesn't matter until your hot path is 12 sequential calls. The platform team owns the sidecar but the app team owns the SLO, and the handoff at incident time is rarely smooth. You're now operating a service mesh, which is a serious distributed system in its own right.
The failure mode nobody mentions
Sidecar crashes silently while the app keeps serving — but without mTLS, without metrics, or without retry policy. Liveness only tests the app port, so health checks stay green; traffic flows, and you discover the gap three days later when a compliance scan catches plaintext between two services that 'have mTLS'. Health-check the sidecar independently and fail the pod if it's down.
When not to use it
A single service, a single language, or a small team that can centralise the concern as a shared library — the operational tax isn't worth it for three services in one repo.