Service Mesh
debt(d8/e8/b8/t6)
Closest to 'silent in production until users hit it' (d8): missing mTLS or duplicated retry logic across PHP microservices isn't caught by any automated tool — istio/linkerd analyze existing config but don't tell you that you should or shouldn't adopt a mesh. Only manifests under production load or security audit.
Closest to 'architectural rework' (e8): adopting (or removing) a service mesh means deploying sidecars across the cluster, reconfiguring networking, and reconciling app-level retries with mesh-level retries. Quick_fix says 'no PHP code change' but the infrastructure rework is substantial; slightly under e9 because PHP code itself stays put.
Closest to 'strong gravitational pull' (b8): once a mesh is in place, every new service, deploy, and debugging session is shaped by it (Envoy config, sidecar lifecycle, mTLS certs). Applies cross-cuttingly to all web/api services. Just under b9 because you can technically peel it off with effort.
Closest to 'serious trap' (t6): misconception is that a mesh is required for microservices when simpler solutions often suffice; plus the double-retry footgun where mesh+app both retry non-idempotently duplicates requests — contradicts the intuition that more resilience layers are safer.
Also Known As
TL;DR
Explanation
A service mesh deploys a proxy sidecar (Envoy) alongside each service. All traffic flows through sidecars — enabling: mTLS between services (zero-trust networking), distributed tracing (automatic span injection), traffic management (canary routing, weighted traffic), circuit breaking, retries, and rate limiting at the infrastructure level. Istio and Linkerd are the main implementations. PHP applications gain these features automatically — no SDK integration needed. The trade-off: operational complexity and latency overhead of an extra network hop per request.
Diagram
flowchart LR
subgraph Service A Pod
APP_A[PHP App]
PROXY_A[Envoy Sidecar]
end
subgraph Service B Pod
APP_B[PHP App]
PROXY_B[Envoy Sidecar]
end
CP[Control Plane<br/>Istio / Linkerd]
APP_A <--> PROXY_A
APP_B <--> PROXY_B
PROXY_A -->|mTLS + traces + retries| PROXY_B
CP -.->|config: routes<br/>policies, certs| PROXY_A & PROXY_B
style APP_A fill:#1f6feb,color:#fff
style APP_B fill:#1f6feb,color:#fff
style PROXY_A fill:#238636,color:#fff
style PROXY_B fill:#238636,color:#fff
style CP fill:#6e40c9,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Adopting a service mesh before needing it — it solves real problems at scale but adds overhead for small setups.
- Not measuring the latency overhead — each hop adds ~1-3ms which compounds in deep call chains.
- Using a service mesh without understanding Envoy config — debugging proxy issues requires mesh knowledge.
- Overlapping retry logic in both app and mesh — double retries cause non-idempotent request duplication.
Code Examples
// Without service mesh: each service implements cross-cutting concerns:
class PaymentClient {
public function charge(array $data): array {
// Each service manually implements:
// - TLS cert management
// - Retry logic with backoff
// - Circuit breaker
// - Trace injection
// - Rate limiting
// Duplicated across every service
}
}
// With service mesh (Istio):
// Sidecar proxy handles automatically:
// - mTLS between all services (zero trust)
// - Automatic retry on 503 (3 attempts, exponential backoff)
// - Circuit breaking at 50% error rate
// - Trace ID injection into all requests
// - Canary routing: 10% to v2, 90% to v1
// PHP service code remains simple:
$response = $this->httpClient->post('http://payment-service/charge', $data);
// Proxy intercepts, adds mTLS, traces, handles retries