envoyproxy/envoy
Wasm
Envoy embeds a WebAssembly runtime so that filters, access loggers, stat sinks, and bootstrap extensions can be written in any language that compiles to Wasm. The host bindings follow the proxy-wasm ABI. The runtimes plug in via source/extensions/wasm_runtime/; the host glue is in source/extensions/common/wasm/.
Why Wasm?
- No process boundary. Plugins run in Envoy's address space, with the same memory model and event loop, but in a sandbox.
- Polyglot. Plugins can be written in Rust, C++, Go (TinyGo), or AssemblyScript and compiled once to a
.wasmmodule. - Hot-loadable. Modules can be loaded over xDS (ECDS) and hot-swapped without restart.
- Sandboxed. No network or filesystem access except through host calls, and host calls are validated.
Where Wasm plugs in
| Concern | Path | Wasm hook |
|---|---|---|
| HTTP filter | source/extensions/filters/http/wasm/ |
proxy_on_request_headers, proxy_on_request_body, etc. |
| Network filter | source/extensions/filters/network/wasm/ |
proxy_on_new_connection, proxy_on_downstream_data. |
| Access logger | source/extensions/access_loggers/wasm/ |
proxy_on_log. |
| Stat sink | source/extensions/stat_sinks/wasm/ |
proxy_on_stats_update. |
| Bootstrap | source/extensions/bootstrap/wasm/ |
Long-lived service, bound at startup. |
Runtimes
Pluggable Wasm engines under source/extensions/wasm_runtime/:
| Engine | Path | Notes |
|---|---|---|
v8 |
v8/ |
The default; uses Chrome's V8 with a Wasm interpreter. |
wasmtime |
wasmtime/ |
Bytecode-alliance reference runtime. |
wamr |
wamr/ |
WebAssembly Micro Runtime. |
null |
null/ |
"Null vm" — runs a C++ plugin compiled into the binary; useful for tests and embedded scenarios where a real Wasm sandbox isn't desired. |
Architecture
graph TB
Config[ECDS / inline config] --> WasmService[Wasm service<br/>bootstrap]
WasmService --> Vm[Wasm VM<br/>per worker thread]
Vm --> Plugin[Plugin instance]
Plugin -->|host calls| HostBinds[Host functions:<br/>get_header / set_header /<br/>http_call / dispatch_request /<br/>...]
HostBinds --> Subs[Existing subsystems<br/>filter manager / cluster mgr /<br/>stats / runtime]A plugin runs in a dedicated VM per worker thread (same threading model as the rest of Envoy — no shared mutable state between workers). The host bindings call back into Envoy's filter manager, cluster manager, stats, runtime, and async client.
Host call vocabulary (proxy-wasm)
The plugin invokes host functions through ABI imports. Common ones:
proxy_get_header_map_value,proxy_set_header_map_value— read/write headers.proxy_get_buffer_bytes,proxy_set_buffer_bytes— body manipulation.proxy_dispatch_http_call— make an outbound HTTP call via cluster manager (the host returns control while the call is in flight).proxy_get_property,proxy_set_property— get/set stream info, dynamic metadata, filter state, request attributes (xds.cluster_metadata.foo, etc.).proxy_log— log to Envoy's logger.proxy_define_metric,proxy_record_metric— register and update stats.proxy_continue_request,proxy_send_local_response— control filter chain.
The full ABI is at proxy-wasm/spec; the host implementations are in source/extensions/common/wasm/context.cc and friends.
Plugin lifecycle
- Configuration arrives (inline or via ECDS).
- Plugin VM is created on each worker (or shared, for singleton plugins).
proxy_on_vm_startruns once per VM.proxy_on_configureruns once per plugin instance with config bytes.- Per-stream callbacks fire as requests flow.
proxy_on_done/proxy_on_deletefire on plugin removal or shutdown.
Loading
http_filters:
- name: my_wasm
typed_config:
'@type': type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
config:
vm_config:
runtime: envoy.wasm.runtime.v8
code:
local:
filename: /etc/envoy/my_filter.wasm
configuration:
'@type': type.googleapis.com/google.protobuf.StringValue
value: '{"my_setting":"value"}'For dynamic loading, the code field can reference a remote URL or be backed by ECDS.
SDKs
Plugin authors don't usually call the proxy-wasm ABI directly. Language-specific SDKs are maintained in separate repos:
- proxy-wasm/proxy-wasm-rust-sdk
- proxy-wasm/proxy-wasm-cpp-sdk
- tetratelabs/proxy-wasm-go-sdk
- proxy-wasm/proxy-wasm-assemblyscript-sdk
When not to use Wasm
- Cold latency. Wasm adds a small but non-zero per-call cost; for the hottest filters, a native C++ filter or a dynamic module may be preferable.
- Polling APIs. Some Envoy capabilities (xDS subscription, stats sink with millions of samples) are too high-throughput to mediate through proxy-wasm gracefully.
- Outbound TCP. Wasm only exposes HTTP and gRPC outbound calls.
See also
- HTTP filters — the wasm HTTP filter.
- Dynamic modules — alternative for native plugins.
- Stats — Wasm stat sink.
- Access logging — Wasm access logger.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.