We've encountered situations where HAProxy struggled with dynamic service discovery in Kubernetes. Retries with jitter were unavailable, and configuration had to be reloaded manually. That's when we implemented Envoy as the data plane — and gained the flexibility that was missing. Envoy is not just a proxy; it's a full platform for microservice architectures. It supports dynamic upstream discovery via xDS API, built-in request tracing, circuit breaking with outlier detection, and retries with jitter. All configuration updates without restarts. This is why Envoy powers Istio, Consul Connect, and AWS App Mesh. Our engineers bring 5+ years of experience and have completed 30+ DevOps projects, ensuring quality implementation. Request a consultation to discuss Envoy integration for your infrastructure. Project cost is determined individually after an audit.
Static configuration: starting without a control plane
For a simple start without a service mesh, a static config suffices. Here's a minimal setup with retry policy:
# envoy.yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
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: "/api/"
route:
cluster: api_service
prefix_rewrite: "/"
timeout: 30s
retry_policy:
retry_on: "5xx,connect-failure"
num_retries: 3
retry_host_predicate:
- name: envoy.retry_host_predicates.previous_hosts
host_selection_retry_max_attempts: 3
- match:
prefix: "/"
route:
cluster: app_service
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: api_service
connect_timeout: 5s
type: STRICT_DNS
lb_policy: LEAST_REQUEST
load_assignment:
cluster_name: api_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: api-service
port_value: 8080
- name: app_service
connect_timeout: 5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: app_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: app-service
port_value: 3000
- endpoint:
address:
socket_address:
address: app-service-2
port_value: 3000
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
Run with Docker:
docker run -d \
-p 10000:10000 \
-p 9901:9901 \
-v ./envoy.yaml:/etc/envoy/envoy.yaml \
envoyproxy/envoy:v1.29-latest \
-c /etc/envoy/envoy.yaml Circuit breaking: preventing cascading failures
When a service starts slowing down or failing, clients (other microservices) can accumulate requests in queues, causing a cascade failure. Circuit breakers in Envoy monitor upstream health and stop sending requests to problematic hosts. Configuration example:
clusters:
- name: payment_service
connect_timeout: 2s
circuit_breakers:
thresholds:
- priority: DEFAULT
max_connections: 1000
max_pending_requests: 500
max_requests: 1000
max_retries: 3
track_remaining: true
outlier_detection:
consecutive_5xx: 5
interval: 10s
base_ejection_time: 30s
max_ejection_percent: 50
consecutive_gateway_failure: 3
enforcing_consecutive_5xx: 100
Outlier Detection: if a host returns 5 consecutive 5xx errors, it is ejected from the pool for 30 seconds. Envoy then sends a probe request — upon success, the host returns.
How outlier detection improves fault tolerance?
Outlier detection in Envoy monitors not only 5xx but also gateway failures, connection failures, and response time. When thresholds are exceeded, the host is excluded from load balancing for a set time. This prevents cascade failures and reduces MTTR. Compared to HAProxy, where manual scripting is required, Envoy provides a ready-made solution configurable via YAML.
Comparison with alternatives: Envoy vs HAProxy and nginx
Envoy offers 3 times more metrics than nginx, but falls behind HAProxy in raw throughput (~200k req/s per core vs ~300k). However, flexibility and observability make it preferable for complex microservice networks.
| Parameter | Envoy | HAProxy | nginx |
|---|---|---|---|
| Dynamic configuration | xDS API, no restart | Only via Lua scripts | Only reload |
| Circuit breaking | Built-in + outlier detection | Manual scripting | No |
| Tracing | Zipkin, Jaeger, Datadog out of the box | No | Via modules |
| Number of metrics | 1000+ via admin endpoint | 200+ | 100+ |
| Throughput (req/s) | ~200k per core | ~300k per core | ~150k per core |
Circuit breaking in Envoy works twice as efficiently as a manual solution on HAProxy, and tracing is available immediately without extra modules. For a custom project, contact us.
Envoy as a sidecar in Kubernetes
The classic pattern is Envoy alongside every pod:
# kubernetes deployment (fragment) spec:
containers:
- name: app
image: myapp:latest
ports:
- containerPort: 8080
- name: envoy
image: envoyproxy/envoy:v1.29-latest
args:
- "-c"
- "/etc/envoy/envoy.yaml"
ports:
- containerPort: 10000
name: proxy
- containerPort: 9901
name: admin
volumeMounts:
- name: envoy-config
mountPath: /etc/envoy
volumes:
- name: envoy-config
configMap:
name: envoy-config
Without Istio, the sidecar is configured manually. With Istio, Envoy is injected automatically via MutatingWebhookConfiguration, and configuration comes from Istiod via xDS.
How does xDS simplify configuration management?
For production infrastructure with dozens of services, static configuration doesn't scale. xDS API allows a control plane (Consul, Pilot in Istio) to dynamically update configuration without restarts:
# envoy-dynamic.yaml — only bootstrap, rest via xDS
dynamic_resources:
lds_config:
resource_api_version: V3
api_config_source:
api_type: GRPC
transport_api_version: V3
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
cds_config:
resource_api_version: V3
api_config_source:
api_type: GRPC
transport_api_version: V3
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
static_resources:
clusters:
- name: xds_cluster
connect_timeout: 5s
type: STATIC
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: control-plane.example.com
port_value: 18000
With xDS, you can change routes, add upstream services, and update policies without restarting. This is especially important for canary deployments and A/B testing.
Our implementation process
We work in stages:
- Audit of current architecture (1-2 days).
- Design configuration with circuit breaking and tracing.
- Implementation on staging with load testing.
- Deployment to production with gradual traffic shifting.
- Documentation and team training.
The result: a ready Envoy infrastructure (static or xDS-based), integration with Istio, Consul, or another control plane, monitoring and alerting (Prometheus + Grafana, dashboards), an operations runbook, and 2 weeks of post-delivery support. Certified engineers ensure stability and performance.
Timeline
| Task | Duration |
|---|---|
| Audit and design | 1-2 days |
| Static config, basic proxy | 1 day |
| Circuit breaking + tracing | 1-2 days |
| xDS with Consul/Pilot, dynamic configuration | 2-3 days |
| Full service mesh + monitoring + documentation | 4-7 days |
Project budget is calculated individually after an audit. Get a consultation — contact us, and we'll prepare a preliminary estimate.







