Envoy Logo

Extension Types

Built On Envoy supports several extension types, each suited to different use cases and workflows. The type field in your extension manifest determines how your extension is packaged and loaded by Envoy.

Rust Dynamic Module Extensions

Rust extensions are compiled HTTP filters that run inside Envoy as native Dynamic Modules. They use the Rust SDK and are compiled to a C-compatible shared library that Envoy loads directly - no intermediate runtime or plugin loader is needed.

Manifest type: rust

name: my-rust-extension
version: 0.1.0
type: rust

How it Works

  1. Your extension implements the HttpFilterConfig and HttpFilter traits from the Rust SDK.
  2. The crate is compiled with cargo build --release to produce a shared library (.so on Linux, .dylib on macOS).
  3. The corresponding init macro wires up the init and filter-creation entry points that Envoy expects from a dynamic module.
  4. At runtime, Envoy loads the shared library directly with no additional host module.

Filter Types

Rust extensions support four filter types, controlled by the optional filterType field in your manifest. The default is http.

Filter Type Envoy Layer Init Macro Description
http (default) HTTP (L7) declare_init_functions! Inspect and modify HTTP requests and responses
network TCP/TLS (L4) declare_network_filter_init_functions! Process raw byte streams before HTTP decoding; useful for custom protocols or connection-level access policies
listener Listener (pre-routing) declare_listener_filter_init_functions! Run logic before a TCP connection is routed to a filter chain; useful for connection acceptance policies and pre-routing inspection
udp_listener UDP Listener declare_udp_listener_filter_init_functions! Process UDP datagrams at the listener level

Getting Started with Rust Extensions

See the Writing Rust Extensions guide for a complete walkthrough of the filter API, lifecycle callbacks, and build process.

Go Extensions

Go extensions are compiled HTTP filters that run inside Envoy through the Dynamic Modules system. They offer full access to the Dynamic Modules Go SDK and support advanced operations such as metrics, body modification, metadata, and local replies.

Manifest type: go

name: my-extension
type: go
composerVersion: 0.2.2

The composerVersion field is required and must match the version of the Composer dynamic module (the special loader module) that will load the plugin.

How it works

  1. Your extension exports a WellKnownHttpFilterConfigFactories() function as its entry point.
  2. The extension is compiled with go build -trimpath -buildmode=plugin to produce a .so file.
  3. At runtime, the Composer’s plugin loader opens the .so file and validates that it was built with the same Go version and matching dependency versions before registering its filters.

You can see a full example in the extensions/composer/example directory.

Getting Started with Go Extensions

See the Writing Go Extensions guide for a complete walkthrough of the filter API, lifecycle callbacks, and build process.

WASM Go Extensions

WASM extensions are HTTP filters written in Go and compiled to WebAssembly. Rather than loading native code into the Envoy process, they run inside Envoy’s built-in WASM runtime as sandboxed modules that communicate with the host through the proxy-wasm ABI. Extensions use the proxy-wasm Go SDK, and the compiled module is executed by Envoy’s V8 runtime (envoy.wasm.runtime.v8), which ships in official Envoy builds.

The WASM sandbox isolates extension code from the Envoy process: a crashing or misbehaving module cannot corrupt Envoy’s memory. This makes WASM a good middle ground between the raw performance of native Go extensions and the process isolation of ExtProc, without the network latency of an out-of-process server.

Manifest type: wasm

name: my-wasm-extension
version: 0.1.0
type: wasm

How it works

  1. Your extension registers a VM context with proxywasm.SetVMContext() and implements the VMContext, PluginContext, and HttpContext interfaces from the proxy-wasm Go SDK.

  2. The module is compiled to WebAssembly with the standard Go toolchain, targeting WASI in c-shared mode so it exports the proxy-wasm ABI functions the SDK relies on:

    env GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o plugin.wasm .
  3. At runtime, Envoy loads the compiled module into a V8 VM and drives the plugin through the proxy-wasm lifecycle callbacks (OnPluginStart, OnHttpResponseHeaders, and so on).

Filter Types

WASM extensions support HTTP (L7) filters only.

When to Use WASM

WASM extensions are a good fit when you need:

  • Sandboxed isolation so extension bugs cannot crash the Envoy process.
  • To run inside Envoy without the network round-trip of an ExtProc server.
  • Portability of a self-contained, runtime-agnostic module.

Limitations: WASM modules run through the proxy-wasm ABI, which exposes a narrower API surface than the Dynamic Modules Go SDK, and the sandbox adds some overhead compared to native Go extensions. For advanced host integrations or maximum performance, consider a Dynamic Module extension instead.

Lua Extensions

Lua extensions use Envoy’s built-in Lua HTTP filter to run scripts directly inside Envoy with no compilation step. This makes them the simplest way to get started with Built On Envoy.

Manifest type: lua

Providing the Lua Script

The lua field in your manifest defines the script source. You can either reference an external file or inline the script directly.

File reference:

name: my-lua-extension
type: lua
lua:
  path: plugin.lua

Inline script:

name: my-lua-extension
type: lua
lua:
  inline: |
    function envoy_on_request(request_handle)
      request_handle:headers():add("x-custom-header", "hello")
    end

    function envoy_on_response(response_handle)
      response_handle:headers():add("x-response-header", "world")
    end

You must provide exactly one of path or inline - not both.

When to Use Lua

Lua extensions are a good fit when you need:

  • Quick header manipulation or request routing logic
  • Simple request/response transformations without a build step
  • Rapid prototyping before investing in a compiled extension

Limitations: Lua extensions have access only to the APIs exposed by Envoy’s Lua filter. For advanced features like custom metrics, body buffering, or tight performance requirements, consider a Go extension instead.

ExtProc extensions

ExtProc extensions are Envoy External Processing gRPC servers that run outside the main Envoy process. The gRPC offers methods to manipulate the request and response metadata and payloads, but is much more complex to use than the Dynamic Modules API.

Using ExtProc extensions introduces latency and serialization overhead, but it is a good approach for extensions that are preferred to run outside the main Envoy process to make sure the extension code cannot affect the Envoy main process.

Manifest type: ext_proc

name: my-extproc-extension
type: ext_proc
version: 0.2.2
extProc:
  grpcPort: 50051
  failureModeAllow: false
  processingMode:
    requestHeaderMode: SEND
    responseHeaderMode: SEND
    requestBodyMode: BUFFERED
    responseBodyMode: NONE

How it works

  1. Your extension implements the Envoy ExternalProcessorServer gRPC service interface.
  2. The extension is compiled into a standalone binary that is started in parallel to Envoy.
  3. Envoy is configured to forward requests and responses to the external processor server.

You can see a full example in the extensions/example-ext-proc directory.