What is Envoy Proxy — Explained for Beginners
Envoy proxy powers Istio, AWS App Mesh, and many service meshes. Here's what it actually does, why it matters, and how it works — explained simply.
You've seen Envoy mentioned everywhere — Istio uses it, AWS App Mesh uses it, Contour uses it. But what actually IS Envoy, and why does everyone use it?
Let me explain it simply.
What Envoy Is
Envoy is a high-performance proxy designed for cloud-native applications. It sits between services and handles network traffic for them.
Think of it like this: instead of your services talking directly to each other, they talk TO Envoy, and Envoy talks to the destination.
Without Envoy:
Service A ──────────────────────── Service B
With Envoy:
Service A → Envoy Sidecar → network → Envoy Sidecar → Service B
Why This Is Useful
When Envoy is in the middle, it can:
- Load balance traffic across multiple instances
- Retry failed requests automatically
- Add timeouts so slow services don't hang everything
- Collect metrics on every request (latency, errors, throughput)
- Handle TLS so services don't need to manage certificates
- Rate limit traffic to protect services from overload
Your application code does none of this — Envoy handles it transparently.
How It's Different From Nginx
Nginx and HAProxy are also proxies. What makes Envoy different?
1. Dynamic configuration — Nginx needs a config file restart. Envoy has xDS APIs — config updates in real-time with zero restarts. This is critical for Kubernetes where services come and go constantly.
2. First-class observability — Envoy emits detailed Prometheus metrics, distributed traces, and access logs out of the box.
3. L4 + L7 — Envoy handles both TCP (L4) and HTTP/gRPC (L7) traffic with equal sophistication.
4. Designed for the sidecar pattern — Envoy was built specifically for microservices, not retrofitted.
Envoy in Istio (The Sidecar Pattern)
In Istio, Envoy runs as a sidecar container next to every pod:
# Kubernetes Pod with Envoy sidecar (injected automatically by Istio)
spec:
containers:
- name: my-app # your app
image: my-app:latest
- name: istio-proxy # Envoy proxy (auto-injected)
image: docker.io/istio/proxyv2:latestYou don't write this — Istio injects it automatically when you label a namespace:
kubectl label namespace production istio-injection=enabledAfter this, every new pod gets an Envoy sidecar. All traffic flows through it.
Key Concepts
Listeners
Where Envoy accepts traffic. Like a port it listens on.
# Envoy listens on port 10000 for incoming traffic
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000Clusters
The upstream services Envoy can forward traffic to.
# Envoy knows about "backend-service" and its endpoints
clusters:
- name: backend-service
load_assignment:
cluster_name: backend-service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 192.168.1.10
port_value: 8080Routes
Rules that match incoming requests and forward to clusters.
# Route /api/* to backend-service, everything else to frontend
route_config:
virtual_hosts:
- name: local_service
routes:
- match:
prefix: "/api"
route:
cluster: backend-service
- match:
prefix: "/"
route:
cluster: frontend-serviceFilters
Middleware that processes requests. Examples: HTTP filter (parses HTTP), gRPC filter, rate limiting filter, JWT auth filter.
xDS APIs — Why Envoy Is Dynamically Configurable
xDS (discovery services) is how control planes configure Envoy at runtime:
- LDS — Listener Discovery Service (add/remove listeners)
- RDS — Route Discovery Service (update routing rules)
- CDS — Cluster Discovery Service (add/remove upstream services)
- EDS — Endpoint Discovery Service (update instance IPs)
Istio's control plane (Pilot) uses xDS to push config to all Envoy sidecars in real-time. When a new pod starts, Envoy learns about it within seconds — no config file restarts.
What Envoy Observability Looks Like
Every Envoy sidecar emits:
Metrics (Prometheus):
# Request rate
envoy_cluster_upstream_rq_total{cluster_name="backend-service"} 15234
# Error rate
envoy_cluster_upstream_rq_5xx{cluster_name="backend-service"} 12
# Latency
envoy_cluster_upstream_rq_time_bucket{le="100"} 14890
Distributed traces — Envoy propagates trace headers (Jaeger/Zipkin/OpenTelemetry compatible)
Access logs:
[2026-05-29T10:23:45.123Z] "GET /api/users HTTP/1.1" 200 -
via_upstream - "-" 0 452 12 12 "-" "curl/7.68.0"
"x-request-id-abc123" "backend-service" "192.168.1.10:8080"
Where Envoy Runs in the Wild
| Product | Envoy Role |
|---|---|
| Istio | Sidecar proxy for all pods |
| AWS App Mesh | Sidecar proxy |
| Contour | Ingress controller |
| Emissary-Ingress | Ingress/API gateway |
| Gloo Edge | API gateway |
| Consul Connect | Service mesh proxy |
Envoy is the networking layer powering most modern service meshes. You don't always configure it directly — Istio or App Mesh does — but understanding what it does helps you debug network issues and understand the metrics it produces.
Learn service mesh and networking in Kubernetes hands-on at KodeKloud — they have dedicated Istio and networking courses with real cluster labs.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
How to Migrate from Ingress-NGINX to Kubernetes Gateway API in 2026
Step-by-step guide to migrating from Ingress-NGINX to Kubernetes Gateway API. Includes YAML examples, implementation choices, testing strategy, and cutover plan.
How to Set Up Kubernetes Gateway API to Replace Ingress (2026 Guide)
The Kubernetes Ingress API is being replaced by the Gateway API. Here's a complete step-by-step guide to setting it up with Nginx Gateway Fabric and migrating from Ingress.
What is a Service Mesh? Explained Simply (No Jargon)
Service mesh sounds complicated but the concept is simple. Here's what it actually does, why teams use it, and whether you need one — explained without the buzzwords.