Library / SDK
envoyproxy/envoy avatar
envoyproxy/envoy

Envoy proxy: a C++ data plane you configure, not code

Cloud-native high-performance edge/middle/service proxy. envoy-maintainers: Use this list to reach all core Envoy maintainers.

28,993 stars5,628 forksC++Apache-2.0

At a glance

What is it?
Envoy is a CNCF-hosted edge and service proxy written in C++, configured through xDS APIs and static YAML. It fits teams that need a programmable data plane; it is a poor fit for anyone who wants a two-line config.
Who is it for?
Adopt Envoy if you run many services and want traffic policy expressed as data that a control plane can push, and if you can absorb the config surface and the Bazel-based build. Do not adopt it as a quick reverse proxy for one hobby app, and do not expect the README to teach you the configuration; it points at the docs site, the examples repository and the FAQ instead.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Envoy solves: traffic policy as data

Most proxies are configured by editing a file on a host and restarting a process. Envoy's design assumption is the opposite: the process is a generic data plane, and the routing, retry, timeout, TLS and load-balancing decisions arrive as structured configuration from something else. The README describes the project as a cloud-native high-performance edge/middle/service proxy, and the repository links a blog post about the universal data plane API, which is the clearest statement of intent in the README. The audience is platform and infrastructure engineers who run container-packaged, dynamically scheduled services and who want one proxy binary to sit at the edge, between services, and in front of a database, with the same configuration model everywhere. If you only need to terminate TLS for a single web app, this is a large amount of machinery for the job.

How the data plane and its configuration fit together

The repository layout makes the split visible. The api/ directory holds the protocol definitions, and the README points at envoyproxy/data-plane-api, described there as a read-only mirror of api/. Listeners accept connections, filter chains decide what to do with them, and clusters describe upstream endpoints. The Go module file shows the control-plane side of the contract: the module github.com/envoyproxy/envoy requires github.com/envoyproxy/go-control-plane/envoy, which is the generated Go binding for those same protobuf definitions. In practice a control plane watches your service registry and pushes configuration over xDS; Envoy applies it without a process restart. The alternative mode is static configuration, where you write the same structures as YAML and start the binary with a config file. Both paths reach the same internal model, which is why the static file is a reasonable way to learn the shape of the API before you automate it. The threading model and stats architecture are covered in separate blog posts linked from the README rather than in the README itself, so the repository is honest about where the design explanation lives.

Installing Envoy and running a first listener

The README does not carry install instructions. It points to the official documentation at envoyproxy.io, the examples repository at github.com/envoyproxy/examples, and the FAQ. Those are the sources to follow for a supported binary or container image; the repository itself is the source tree, and its developer path is a Bazel build. The top-level entries confirm that: MODULE.bazel, .bazelrc, .bazelversion and a BUILD file sit next to the source directories, and CONTRIBUTING.md points contributors at the CI documentation for building and running tests with Docker.

Because the README gives no runnable example, there is no configuration snippet to reproduce here. The repository does publish a control-plane dependency you can read directly. The go.mod file at the root declares the Go module and its Envoy-related requirement, which is the binding a control plane uses to build the xDS messages Envoy consumes.

go
module github.com/envoyproxy/envoy

go 1.25.0

require (
	github.com/envoyproxy/go-control-plane/envoy v1.37.0
	google.golang.org/protobuf v1.36.11
)

What a reader should take from that block is the direction of the contract: the proxy consumes protobuf messages, and the Go bindings are versioned alongside them. The Rust side is equally explicit. The root Cargo.toml is a workspace whose members are the dynamic module SDK and its builtin extensions, which is where in-process extension code lives.

toml
[workspace]
members = ["source/extensions/dynamic_modules/sdk/rust", "source/extensions/dynamic_modules/builtin_extensions", "test/extensions/dynamic_modules/test_data/rust"]
resolver = "2"

There is no command in the README to start the binary, no documented flag, and no example config file in the repository root. Anyone who wants a first working listener has to go to the docs site or the examples repository, which is a real gap for a project of this size.

Where Envoy is the wrong tool

Three constraints stand out. First, the configuration surface is large because the feature surface is large; the repository ships DEPRECATED.md and API_VERSION.txt precisely because fields and API versions move, and a static config that works today can require edits across a release boundary. Second, the project is written in C++ and built with Bazel, so extending it in-process means working inside a large C++ codebase; the CONTRIBUTING.md acknowledges this by arguing that modern C++ is less intimidating than newcomers expect, which is a fair signal that the barrier is real. Third, platform coverage is uneven by policy. The README states that ppc64le builds are not covered by the Envoy security policy and are best-effort, not maintained by the Envoy maintainers. If you are on an architecture outside the supported set, you are outside the security promise as well. For a single internal service behind a load balancer, a smaller proxy will be faster to operate and easier to debug.

Envoy next to HAProxy and nginx

The honest comparison is about configuration delivery, not raw throughput. nginx and HAProxy are configured from files that you manage; reloading means signalling or restarting a process, and dynamic upstream changes usually mean templating those files and reloading anyway. Envoy's difference is that the same routing model is exposed as protobuf APIs, so a control plane can add a cluster or change a route without touching a file on the host. That is the reason service meshes and API gateways build on it. The cost is that you now need something to produce that configuration, and the Go module in this repository shows what that dependency looks like: go-control-plane and protobuf bindings are part of the contract. If you never plan to run a control plane, you are paying Envoy's complexity for a static proxy, and a file-based proxy is the simpler answer.

Release cadence, upgrades and the licence

Three release lines were tagged within roughly a day of each other in late August 2026: v1.39.1, v1.38.4 and v1.37.6. That pattern tells you the project maintains parallel branches and backports fixes, so you can stay on a slightly older line and still receive patches, but you must choose a line deliberately. The repository carries RELEASES.md and BACKPORTS.md for the process, and DEPRECATED.md for fields on the way out. Upgrading is therefore a scheduled activity, not a background one: read the deprecation list, check the changelogs/ directory for your line, and test the config against the new binary before rolling it out. The licence is Apache-2.0, which permits commercial use and modification and includes a patent grant; the repository also carries a NOTICE file, and Apache-2.0 obligations around that notice and attribution are worth reviewing with your own counsel rather than taken from an article.

Extending Envoy without forking the C++ tree

The Cargo.toml at the repository root is a workspace whose members are all under source/extensions/dynamic_modules, including an sdk/rust crate and a builtin_extensions crate. That is the route for teams that want custom logic without patching the core: write a dynamic module in Rust against the provided SDK, and the extension lives outside the main C++ build. It is a narrower door than a general plugin system, and it is aimed at extensions rather than at rewriting listeners. The repository also points at envoy-filter-example for the traditional path of adding filters and linking against the main tree, which is the heavier option. Choosing between them is a maintenance decision: a dynamic module tracks the SDK, while a linked filter tracks the core build.

Editorial conclusion

Adopt Envoy if you run many services and want traffic policy expressed as data that a control plane can push, and if you can absorb the config surface and the Bazel-based build. Do not adopt it as a quick reverse proxy for one hobby app, and do not expect the README to teach you the configuration; it points at the docs site, the examples repository and the FAQ instead. Before committing, verify three things in your own environment: which release line you will pin (v1.39.1, v1.38.4 and v1.37.6 were all tagged within a day of each other, so backports matter), whether your platform is covered by the security policy (the README states ppc64le builds are best-effort and not maintained by the maintainers), and how you will generate xDS config, since hand-written static YAML does not scale past a handful of clusters.

Frequently asked questions

How do I install the Envoy proxy?

The README does not include install steps. It directs readers to the official documentation at envoyproxy.io, the examples repository at github.com/envoyproxy/examples, and the FAQ page linked from the README.

How do I use the Envoy proxy?

You give the binary a configuration describing listeners, filter chains and clusters, either as static YAML or pushed over the xDS APIs defined in the api/ directory. The examples repository linked from the README is the intended starting point.

How do I use Envoy?

Start it with a config file passed on the command line and route traffic through the listener you defined. The repository's own quick-start material lives in CONTRIBUTING.md and the CI docs, which describe building and testing with Docker.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/envoyproxy-envoy.svg)](https://hysenlabs.com/projects/envoyproxy-envoy)