Envoy vs NGINX: Which Proxy Fits Your API Gateway?
NGINX, released in 2004 by Russian developer Igor Sysoev, is a battle-tested web server, reverse proxy, and load balancer built around static configuration files and a worker-process model. Envoy, open sourced by Lyft in 2016, is a proxy built for microservices and service mesh traffic. It is built around dynamic configuration through its xDS API and deep observability. Neither one is simply "better." Which proxy fits depends on your environment, your traffic patterns, and how much of your infrastructure is already cloud native. This piece walks through the technical differences that actually matter when you're picking a proxy for an API gateway or a service mesh data plane.
What Is NGINX?
NGINX started as a web server. Igor Sysoev built it in the early 2000s to solve the C10K problem: handling ten thousand concurrent connections on a single machine. Servers like Apache at the time used a process-per-connection model that didn't scale well. His answer was an event-driven, asynchronous architecture: a small master process and a fixed pool of worker processes handling I/O through non-blocking calls. That design is still at the core of NGINX today, and it's a big part of why the software scaled so well on modest hardware.
Today NGINX is used as a web server, reverse proxy, load balancer, and TLS termination point, and it remains one of the most widely deployed pieces of infrastructure software on the internet. Current data from W3Techs puts it at about 31% of websites with a known web server, second only to Cloudflare's server and well ahead of Apache (about 22%). NGINX is also highly extensible: the OpenResty project builds on it with Lua scripting, and a large ecosystem of open-source API gateways use NGINX as their underlying data plane. What it's traditionally best at is static content, high-traffic websites, and reverse proxying in front of a relatively stable set of backends.
What Is Envoy?
Envoy has a different origin story. Lyft built it internally starting in 2015 to solve a problem NGINX and HAProxy weren't designed for: routing traffic reliably between dozens, then hundreds, of microservices as the company moved off a monolith. The team needed a proxy that could discover backends dynamically, push configuration changes without dropping connections, and expose detailed metrics out of the box. Lyft open sourced the result in September 2016. Envoy quickly became the reference data plane for service mesh projects like Istio, plus a foundation for edge gateways and, increasingly, implementations of the Kubernetes Gateway API.
Envoy is written in C++ and built around a threading model that lets a single process use every CPU core available to it. Its defining feature is xDS, a family of discovery APIs that let a control plane push listener, route, and cluster configuration to Envoy at runtime. Envoy can also run from a static bootstrap file with no control plane at all, but xDS is what most production, Kubernetes-native deployments use it for. That architecture is what makes Envoy a natural fit for cloud-native API gateway deployments, where backends scale up and down constantly and configuration needs to keep pace.
Configuration Model: Static Files vs. Dynamic API
This is the sharpest technical difference between the two proxies, and it's worth treating as more than a bullet point.

NGINX is configured through text files. You edit the config, then either restart the process or send it a reload signal so it re-reads the file and forks new worker processes. A reload is graceful. Old workers stop accepting new connections but keep serving requests already in progress, then exit. Long-lived connections, like WebSockets or streaming gRPC calls, can keep running under the pre-reload configuration for a while afterward. The open-source version has no API for pushing changes at runtime. NGINX Plus, the commercial edition, adds some dynamic capability on top, but the open-source core still centers on a file you write and a reload you trigger.
Envoy works the other way around. Its xDS protocol lets a control plane stream configuration to a running Envoy instance over gRPC, and Envoy applies it without a restart and without dropping in-flight connections. Routes, TLS certificates, and backend clusters can all change while traffic keeps flowing through the same process. This isn't a minor operational nicety. It's the reason Envoy-based controllers can update thousands of routes across a large cluster in near real time. It also connects directly to why the Kubernetes ecosystem is shifting away from reload-based Ingress controllers, which we'll get to below.
| NGINX | Envoy | |
|---|---|---|
| Config source | Static file | Dynamic API (xDS) |
| Applying changes | Reload / restart | Streamed at runtime |
| In-flight connections | Not dropped, but long-lived ones may outlive the reload on old config | Unaffected |
| Built-in dynamic API | NGINX Plus only | Yes, open source |
Performance: What the Benchmarks Actually Show
Performance comparisons for proxies are noisy, and results depend heavily on configuration, hardware, and workload. With that caveat up front, two independent data points are worth citing directly.
Loggly published a five-way load balancer benchmark in December 2018. It tested NGINX, HAProxy, Envoy, Traefik, and Amazon ALB with default configurations, on a single two-vCPU AWS instance (ALB, as a managed service, aside). The test covered three concurrency levels and both HTTP and HTTPS. Envoy had the highest raw throughput in that test, particularly at moderate concurrency. HAProxy narrowly beat it on HTTP latency, and the two were roughly tied on HTTPS latency. Loggly's own conclusion is worth repeating: different configurations and different workloads produce different results, so treat any single benchmark, including this one, as a starting point for your own testing rather than a universal verdict. It's also nearly eight years old, so treat it as one dated data point rather than a current performance ranking.
Resource footprint is a more durable comparison point. A 2025 VPS benchmark from Onidel ran HAProxy, NGINX, and Envoy with comparable configurations on AMD EPYC-based VPS instances. It found NGINX using roughly 80MB of RAM against Envoy's roughly 150MB. That gap reflects a real trade-off rather than a simple win for either side. Envoy's richer feature set, built-in observability, and dynamic configuration machinery cost more memory than NGINX's leaner, more static design. If you're running thousands of proxy instances, that difference adds up. If you're running a handful of gateway pods, it usually doesn't matter much.
Don't pick a proxy off a benchmark chart. Benchmark your own workload, on your own hardware, with your own traffic shape, and treat published numbers as a sanity check rather than a decision.
Extensibility: Lua and Modules vs. WASM and Filter Chains
NGINX extends through two main paths: a large ecosystem of third-party C modules, and Lua scripting through OpenResty. Both work well and are widely used in production. But writing custom logic in Lua or C is a real skill investment, and advanced NGINX configurations can get complicated fast once you're chaining multiple modules together.
Envoy extends through native C++ filters and through WebAssembly (WASM) filters, which let you write extensions in languages like Rust or Go and run them sandboxed inside the proxy. Envoy also has native support for gRPC and HTTP/2 filter chains, which makes it a strong fit for teams already building on those protocols. Every source that covers this agrees on the trade-off: Envoy's extensibility model demands more engineering investment than NGINX's. Writing a native Envoy filter in C++ is a bigger lift than writing a Lua script, and even WASM filters require more setup than dropping an NGINX module into place.
Service Mesh and Cloud-Native Fit
This is Envoy's clearest structural advantage, and it's worth being direct about it rather than treating it as one feature among many.
Envoy has native service discovery, and it's the data plane underneath Istio and several other service mesh implementations. Its dynamic configuration model means a control plane can push routing, retry, and circuit-breaking rules to every proxy in a mesh without touching individual nodes. It also has growing native support for the Kubernetes Gateway API, the CRD-based successor to the older Ingress API.
NGINX's story in Kubernetes has historically run through Ingress-NGINX, a specific open-source Ingress controller that translates Kubernetes Ingress resources into NGINX configuration. That project is a separate thing from NGINX the web server, and it was retired in March 2026, which we cover in detail below. NGINX itself isn't going anywhere. Its role as the default way to get traffic into a Kubernetes cluster is what's changing.
Observability: Metrics, Tracing, and Logging Out of the Box
Envoy ships with detailed built-in statistics, hooks for distributed tracing through Zipkin, Jaeger, or OpenTelemetry, and structured access logs by default. For teams building observable systems from day one, this is widely cited as one of Envoy's strongest differentiators. You don't need to bolt on a separate module to get per-route latency histograms or trace propagation.
NGINX's observability story typically requires more manual work. Structured access logging is straightforward to configure, but detailed request-level metrics and native distributed tracing generally require third-party modules or the paid NGINX Plus tier. Neither approach is wrong, but if deep, out-of-the-box observability is a hard requirement, Envoy starts further ahead.
Envoy vs. NGINX: Side-by-Side Comparison
| NGINX | Envoy | |
|---|---|---|
| Proxy type | Web server / reverse proxy | Edge and service proxy |
| Language | C | C++ |
| Configuration model | Static file, reload required | Dynamic (xDS), no reload |
| HTTP/1.1, HTTP/2 | Yes | Yes |
| HTTP/3 | Experimental (since 1.25.0) | Yes |
| gRPC | Via modules | Native |
| Extensibility | Lua (OpenResty), C modules | WASM, native C++ filters |
| Service discovery | Limited, mostly static/DNS | Native, dynamic |
| Observability | Manual / NGINX Plus | Built-in metrics, tracing, logs |
| Typical use case | Web serving, static content, reverse proxy | Service mesh, microservices, Kubernetes ingress |
Which Should You Choose?
A widely shared framing from a Hacker News discussion on this exact topic put it well: Envoy solves a specific, narrow problem extremely well, while NGINX solves a broader set of problems reasonably well. That's a useful way to think about the decision.
Choose NGINX if you're serving static content or traditional web traffic. It also fits when your backend topology is stable, your team already knows NGINX configuration well, or you want a proxy hardened by two decades of production use. It's still an excellent choice for a huge range of workloads.
Choose Envoy if you're running microservices that scale dynamically or need a service mesh data plane. It's also the right call when you're building on Kubernetes and want native Gateway API support, or when rich observability and dynamic configuration matter more than a smaller memory footprint. It's the more common starting point today for teams building an API management platform on a modern data plane instead of layering API concerns onto a web server.
Neither proxy is going away. This isn't a case where one side is simply wrong, and for a lot of workloads either one will do the job fine. But for teams building cloud-native, Kubernetes-native infrastructure specifically, the ecosystem's center of gravity has been moving toward Envoy-based gateways for a few years, and one recent, concrete event is accelerating that shift.
The Kubernetes Shift: Why Envoy Is Becoming the Default Ingress Choice
Ingress-NGINX, the most widely deployed Ingress controller in Kubernetes, has been retired. Best-effort maintenance ended in March 2026. There are no further releases, no bug fixes, and no security patches. Existing deployments keep running, and existing Helm charts and container images stay available, but the project no longer moves forward.
It's worth being precise here, because this point causes real confusion. NGINX the web server and reverse proxy is not going anywhere, and it's actively maintained by F5 as one of the most widely used pieces of web infrastructure in the world. Ingress-NGINX is a separate, specific project: a Kubernetes controller that watches Ingress resources and translates them into NGINX configuration. That controller is what's being retired, not NGINX itself. Don't confuse it with F5's separately maintained NGINX Ingress Controller (the nginx/kubernetes-ingress project). That is a different codebase, built and supported by F5, and this retirement doesn't affect it.
The retirement traces back to a few compounding problems. Ingress-NGINX relied heavily on annotations to extend the base Ingress API. Those annotations are freeform strings with no schema validation. They can fail silently in ways that are hard to catch before deployment. Some of them also allowed arbitrary NGINX configuration snippets. That created a security surface the maintainers could not sustainably audit. On top of that technical debt, the project had relied on only one or two active maintainers for years, a workload mismatch that eventually became unsustainable for a project at that scale.
The Kubernetes community's recommended path forward is the Gateway API, a newer, more structured set of CRDs for modeling traffic routing. Ingress conflates infrastructure, security, and application concerns into a single resource. The Gateway API separates those responsibilities instead: infrastructure teams manage Gateways, and application teams attach Routes to them. The whole model is strongly typed, so misconfigurations get caught at the API level instead of failing silently at runtime.
The Gateway API specification itself is proxy-agnostic, and its list of conformant implementations includes non-Envoy options too, among them NGINX Gateway Fabric, Traefik Proxy, Cilium, and the HAProxy-based N42 Gateway. But several of the most widely adopted implementations, including Envoy Gateway, Istio, and kgateway, do use Envoy as their data plane. That's a big part of why Envoy has become such a common default for teams making this specific migration, even though it isn't the only path.
How WSO2 API Platform Gateway Builds on Envoy
The API Gateway in the WSO2 API Platform is a concrete example of a platform that made this architectural bet directly. It's worth walking through, because the reasoning maps closely to everything covered above.
The gateway has two parts. The Gateway Controller is its control plane. It pushes API and route configuration to the Gateway Runtime over xDS. The runtime uses Envoy Proxy as its router, so routing and TLS changes apply without the full reloads of NGINX-based controllers. A Policy Engine, which runs as an Envoy ext_proc filter, executes request and response policies. Go policies are compiled into it, and a Python Executor runs Python policies. On Kubernetes, the Gateway Operator accepts WSO2's own CRDs (APIGateway and RestApi) or standard Gateway API resources (GatewayClass, Gateway, and HTTPRoute). Platform teams work with declarative, Kubernetes-native configuration rather than a proprietary layer.
On top of ingress and routing, the gateway handles API concerns on the same data plane. Authentication, rate limiting, header manipulation, and analytics all run as policies. Replicas share rate-limit counters through Redis. You don't need a separate Ingress controller in front of a separate API gateway. Both roles run on the same Envoy-based layer.
For outbound LLM traffic, the platform uses the WSO2 AI Gateway, which runs on the same runtime. Its LLM proxies front providers such as OpenAI, Azure OpenAI, Anthropic, Gemini, Mistral, and AWS Bedrock. They add centralized credentials, token-based rate limits, guardrails, and usage analytics to that outbound path. That's a current concern for teams managing multi-provider LLM usage. Most general-purpose proxy comparisons don't cover it.
For observability, the gateway exposes Prometheus metrics (with Grafana dashboards) and distributed tracing through Jaeger. It sends analytics to Moesif or to any OpenTelemetry-compatible backend. On Kubernetes, the operator reports status on its resources. That fits the Gateway API's structured status model, which surfaces explicit success and failure conditions instead of the sparse status output Ingress typically provides.
None of this is a hypothetical bet. WSO2 built its current gateway on Envoy for the same reasons this piece has walked through: dynamic configuration, built-in observability, and a Kubernetes-native model. If you're specifically migrating off Ingress-NGINX in Kubernetes rather than making a general proxy decision, the deeper walkthrough of that transition is worth reading in WSO2's Ingress-NGINX retirement post.
Conclusion
This isn't a story of Envoy being good and NGINX being bad. It's a fit question, and for a large share of traditional web-serving workloads, NGINX is still the right, well-proven answer. But for Kubernetes-native teams specifically, that fit is shifting, driven by a concrete, dated event: the retirement of Ingress-NGINX and the Kubernetes ecosystem's move toward the Gateway API. Envoy-based gateways are becoming the default path for that transition. That isn't hype. Their configuration model, observability, and Kubernetes-native tooling line up with where cloud-native infrastructure is heading.
Frequently Asked Questions
What's the difference between Envoy and NGINX?
NGINX is a web server and reverse proxy configured through static files, built in 2004 around an event-driven worker model. Envoy is a proxy built at Lyft starting in 2015 and open sourced in 2016 for microservices, configured dynamically through its xDS API, with built-in observability and native service discovery.
Is NGINX going end of life?
No. NGINX the web server and reverse proxy is actively maintained by F5. What's being retired is Ingress-NGINX, a separate Kubernetes Ingress controller project, and its best-effort maintenance ended in March 2026.
Is Envoy based on NGINX?
No. Envoy was built independently at Lyft, written in C++, and designed specifically for dynamic microservice environments. It shares no codebase with NGINX, which is written in C and predates Envoy by more than a decade.
Is there a better alternative to NGINX?
"Better" depends on the job. For static content and traditional web traffic, NGINX remains an excellent choice. For microservices, service mesh, and Kubernetes-native environments that need dynamic configuration and rich observability, Envoy is generally the stronger fit.