sidecar-pattern
Auxiliary service sharing lifecycle with main service. Trigger: When adding logging, monitoring, or auth proxy to microservices without code changes.
Sidecar Pattern
Deploys auxiliary services alongside the main application, sharing lifecycle. In Kubernetes, sidecars run in the same pod and share a network namespace (communicate via localhost). In Docker Compose, sidecars share a Docker network (communicate via service name). Common in microservices for cross-cutting concerns.
When to Use
- Adding logging, monitoring, or security to microservices without code changes
- Service mesh (Envoy, Istio) for traffic management and observability
- Centralizing TLS termination or auth proxy across services
- Configuration management that updates dynamically
Don't use for:
- Monolithic applications (use middleware instead)
- Single simple services where overhead isn't justified
- Tight coupling between sidecar and main app logic
Critical Patterns
✅ REQUIRED: Shared Lifecycle
Sidecar and main service start, stop, and scale together.
# Docker Compose — shared lifecycle (shared Docker network, not network namespace)
# Services communicate via service name, e.g., http://order-service:3000
services:
order-service:
build: ./order-service
ports: ["3000:3000"]
order-sidecar-logger:
image: fluent/fluentd
volumes:
- ./logs:/fluentd/log
- ./fluent.conf:/fluentd/etc/fluent.conf
depends_on: [order-service] # Starts after; stops when compose stack stops
✅ REQUIRED: Network Transparency
Main service unaware of sidecar. Sidecar intercepts/adds capabilities transparently.
# Kubernetes — sidecar in same pod (shared network namespace)
spec:
containers:
- name: app
image: myapp:latest
ports: [{containerPort: 3000}]
- name: envoy-proxy
image: envoyproxy/envoy:latest
ports: [{containerPort: 9901}]
# Intercepts all traffic on behalf of app
✅ REQUIRED: Single Responsibility per Sidecar
Each sidecar handles one cross-cutting concern.
✅ logging-sidecar → only log aggregation
✅ metrics-sidecar → only Prometheus scraping
✅ auth-proxy-sidecar → only authentication
❌ utility-sidecar → logging + metrics + auth (too many responsibilities)
❌ NEVER: Business Logic in Sidecar
❌ Sidecar validates business rules or transforms domain data
✅ Sidecar handles infrastructure concerns only (logs, metrics, TLS, retries)
✅ REQUIRED: Common Deployment Configurations
Service mesh (Envoy/Istio):
→ mTLS between services, circuit breaking, load balancing, observability
Logging aggregation (Fluentd/Filebeat):
→ Tail app logs → ship to Elasticsearch/Splunk
Auth proxy (oauth2-proxy):
→ Intercept HTTP requests → validate JWT/OAuth → forward to app
Config watcher (Consul/etcd agent):
→ Watch for config changes → update shared volume → app hot-reloads
Decision Tree
Adding cross-cutting concern to multiple services?
→ Sidecar pattern → one sidecar per concern per service
Cross-cutting concern requires code changes to main app?
→ Not a pure sidecar → Consider library/middleware instead
Kubernetes deployment?
→ Sidecar as additional container in same Pod spec
Docker Compose deployment?
→ Sidecar as depends_on service sharing network
Business logic needed?
→ Do NOT put in sidecar → belongs in main app
Example
# Kubernetes — Envoy sidecar for mTLS and observability
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: payment-service
image: payment:latest
ports: [{containerPort: 8080}]
- name: envoy # Sidecar
image: envoyproxy/envoy:v1.28
args: ["-c", "/etc/envoy/config.yaml"]
ports:
- containerPort: 9090 # Metrics
- containerPort: 9901 # Admin
Edge Cases
Resource sharing: Sidecar and app share CPU/memory in the pod. Over-provisioned sidecars starve main app. Set resource limits explicitly.
Startup ordering: App may start before sidecar is ready. Use initContainers or readiness probes to ensure sidecar is healthy first.
Debugging: Distributed tracing (Jaeger/Zipkin) through sidecar adds correlation IDs. Ensure app propagates trace headers.
Resources
- deployment-patterns.md — Full Docker/Kubernetes examples, service mesh config, monitoring setup