Loading content...
While we've discussed API Gateway products built on Envoy, understanding Envoy itself is essential for any serious distributed systems practitioner. Envoy isn't just another proxy—it's become the foundational data plane for modern cloud-native infrastructure.
Born at Lyft in 2016 to solve service mesh challenges, Envoy is now a CNCF graduated project powering an extraordinary range of systems: Istio, Ambassador, Contour, AWS App Mesh, Gloo Edge, Consul Connect, and many more. Whether you choose Envoy directly or through an abstraction, understanding its architecture is invaluable.
This page provides a comprehensive exploration of Envoy's architecture, configuration model, extensibility mechanisms, and direct deployment scenarios.
By the end of this page, you will understand Envoy's architecture and design philosophy, the xDS dynamic configuration APIs, filter chains and extensibility, performance characteristics, and when to use Envoy directly versus through abstraction layers.
Envoy was designed with specific goals that differentiate it from traditional proxies:
| Concept | Description | Example |
|---|---|---|
| Downstream | Client connecting to Envoy | Browser, mobile app, another service |
| Upstream | Service Envoy proxies to | Your backend API server |
| Listener | Named network location Envoy binds to | 0.0.0.0:8080 |
| Cluster | Group of logically similar upstreams | 'user-service' cluster |
| Endpoint | IP/port of a specific upstream instance | 10.0.1.5:8080 |
| Filter | Processing unit in request/response path | Router, AuthN, Rate Limit |
| Route | Rules mapping requests to clusters | /api/users → user-service |
┌─────────────────────────────────────────────────────────────────────────────────┐│ ENVOY PROXY │├─────────────────────────────────────────────────────────────────────────────────┤│ ││ Downstream (Client) ││ │ ││ ▼ ││ ┌─────────────────┐ ││ │ LISTENER │ ← Bind address (0.0.0.0:8080) ││ │ (Filter Chain) │ ││ └────────┬────────┘ ││ │ ││ ▼ ││ ┌───────────────────────────────────────────────────────────┐ ││ │ FILTER CHAIN │ ││ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ ││ │ │ TLS │→ │ HTTP │→ │ ExtAuthz │→ │ Router │ │ ││ │ │ Filter │ │ Conn Mgr│ │ Filter │ │ Filter │ │ ││ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ ││ └───────────────────────────────────────────────────────────┘ ││ │ ││ ▼ ││ ┌─────────────────┐ (Route Match: /api/users → user-service) ││ │ ROUTES │ ││ └────────┬────────┘ ││ │ ││ ▼ ││ ┌─────────────────┐ ││ │ CLUSTER │ ← user-service ││ │ (Load Balance) │ ← Round-robin, least-request, etc. ││ └────────┬────────┘ ││ │ ││ ▼ ││ ┌─────────────────┐ ││ │ ENDPOINTS │ ← 10.0.1.5:8080, 10.0.1.6:8080 ││ │ (Health Check) │ ← Active/passive health checking ││ └────────┬────────┘ ││ │ ││ ▼ ││ Upstream (Backend Service) ││ │└─────────────────────────────────────────────────────────────────────────────────┘Think of Envoy as: Listeners receive connections → Filter chains process requests → Routes select clusters → Clusters load-balance across endpoints. Each step is configurable and observable.
The xDS APIs are Envoy's killer feature. They enable fully dynamic configuration without restarts—something revolutionary when Envoy launched.
| API | Name | Configures | Update Impact |
|---|---|---|---|
| LDS | Listener Discovery | Listeners, filter chains | Adds/removes ports |
| RDS | Route Discovery | Virtual hosts, routes | Routing rule changes |
| CDS | Cluster Discovery | Upstream clusters | New services |
| EDS | Endpoint Discovery | Cluster endpoints | Instance scaling |
| SDS | Secret Discovery | TLS certificates | Cert rotation |
| VHDS | Virtual Host Discovery | Per-route virtual hosts | Large route tables |
| RTDS | Runtime Discovery | Runtime configuration | Feature flags |
Envoy connects to an xDS server (control plane) via gRPC streaming:
┌─────────────────┐ gRPC Stream ┌─────────────────┐
│ │ ←──── Discovery ──────── │ │
│ Envoy Proxy │ Requests │ xDS Server │
│ (Data Plane) │ ─────── xDS ────────────► │ (Control Plane)│
│ │ Responses │ │
└─────────────────┘ └─────────────────┘
xDS servers include:
ADS multiplexes all xDS types over a single gRPC stream, ensuring configuration consistency and ordering:
# Envoy bootstrap config with ADS
node:
id: envoy-1
cluster: edge-cluster
dynamic_resources:
ads_config:
api_type: GRPC
transport_api_version: V3
grpc_services:
- envoy_grpc:
cluster_name: xds-cluster
cds_config:
ads: {}
lds_config:
ads: {}
xDS v3 supports delta (incremental) updates—only changed resources are transmitted. This is critical for large deployments with thousands of routes or endpoints where full config transmission would be prohibitively expensive.
Envoy's filter chain model provides extensibility at multiple levels.
| Type | Level | Examples | Use Case |
|---|---|---|---|
| Listener Filters | L4 (connection) | TLS Inspector, Proxy Protocol | Multi-protocol detection |
| Network Filters | L4 (stream) | TCP Proxy, HTTP Connection Manager | Protocol handling |
| HTTP Filters | L7 (request) | Router, ExtAuthz, CORS, Rate Limit | Request processing |
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
listeners: - name: http_listener address: socket_address: address: 0.0.0.0 port_value: 8080 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http codec_type: AUTO route_config: name: local_route virtual_hosts: - name: backend domains: ["*"] routes: - match: prefix: "/" route: cluster: backend_service http_filters: # 1. External Authentication - name: envoy.filters.http.ext_authz typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz grpc_service: envoy_grpc: cluster_name: auth_service transport_api_version: V3 # 2. Rate Limiting - name: envoy.filters.http.ratelimit typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit domain: production rate_limit_service: grpc_service: envoy_grpc: cluster_name: rate_limit_service # 3. Router (terminal filter - must be last) - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.RouterLua Filters — Inline scripting for simple transformations:
- name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
inline_code: |
function envoy_on_request(handle)
handle:headers():add("X-Custom-Header", "value")
end
WASM (WebAssembly) Filters — Portable, sandboxed extensions:
Lua: Simple header manipulation, request logging (low overhead). WASM: Complex logic, portable across platforms (medium overhead). External services (ExtAuthz, RateLimit): Full-featured, language-agnostic (network overhead). Choose based on complexity and latency requirements.
Observability isn't an add-on in Envoy—it's a core design principle.
Envoy exposes comprehensive metrics via /stats endpoint in Prometheus format:
123456789101112131415161718192021
stats_sinks: - name: envoy.stat_sinks.statsd typed_config: "@type": type.googleapis.com/envoy.config.metrics.v3.StatsdSink address: socket_address: address: statsd port_value: 8125 - name: envoy.stat_sinks.metrics_service typed_config: "@type": type.googleapis.com/envoy.config.metrics.v3.MetricsServiceConfig grpc_service: envoy_grpc: cluster_name: metrics_cluster stats_config: stats_tags: - tag_name: service regex: "^cluster\.(.*?)\." use_all_default_tags: trueEnvoy integrates with major tracing systems:
Highly configurable access logs with format customization:
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: /dev/stdout
log_format:
json_format:
time: "%START_TIME%"
method: "%REQ(:METHOD)%"
path: "%REQ(:PATH)%"
status: "%RESPONSE_CODE%"
duration: "%DURATION%"
upstream: "%UPSTREAM_HOST%"
trace_id: "%REQ(X-REQUEST-ID)%"
Envoy's C++ implementation and event-driven architecture deliver exceptional performance.
| Metric | Value | Conditions |
|---|---|---|
| Added Latency | < 1ms P50, < 2ms P99 | Simple routing, no filters |
| Throughput | ~100K RPS per core | Small payloads, HTTP/1.1 |
| Memory per connection | ~20KB | HTTP/1.1, minimal config |
| Connection capacity | 50K+ per instance | Depends on memory |
| Config reload | ~0ms (xDS) | No connection drops |
Envoy memory scales with:
Envoy generates stats per-cluster, per-route, per-endpoint. With thousands of routes and endpoints, stats memory can explode. Use stats_matcher to limit stats collection in high-cardinality environments.
While many use Envoy through abstraction layers, there are compelling scenarios for direct usage:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
admin: address: socket_address: address: 0.0.0.0 port_value: 9901 static_resources: listeners: - name: http_listener address: socket_address: address: 0.0.0.0 port_value: 8080 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress route_config: name: local_routes virtual_hosts: - name: services domains: ["*"] routes: - match: { prefix: "/api/users" } route: { cluster: user_service } - match: { prefix: "/api/orders" } route: { cluster: order_service } http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: user_service connect_timeout: 5s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: user_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: user-service port_value: 8080 health_checks: - timeout: 5s interval: 10s unhealthy_threshold: 3 healthy_threshold: 2 http_health_check: path: /health - name: order_service connect_timeout: 5s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: order_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: order-service port_value: 8080What's Next:
Having explored the major API Gateway technologies—Kong, AWS API Gateway, Ambassador, and Envoy—we'll conclude with a decision framework: How to Choose an API Gateway for your specific requirements.
You now understand Envoy's architecture, xDS configuration model, filter chains, observability features, and performance characteristics. This knowledge applies whether using Envoy directly or through abstraction layers.