Arion gives you three ways to run your own code on every HTTP request: a WebAssembly filter loaded into the proxy, an external processing service called over gRPC, or a native filter compiled into the binary. All three plug into the same HTTP filter chain — the difference is where your code runs and what it costs to get it there.
Why it matters
Most gateway behaviour is configuration: routing, TLS, rate limits, JWT validation. Extension is for the part that is genuinely yours — a bespoke auth handshake, request rewriting driven by your own data, a protocol adaptation no config flag covers. Picking the right extension point early matters because the three options trade off latency, isolation, and operational effort differently, and switching later means rewriting.
How it works
Every option is an HTTP filter inside the filter chain. Filters run in configured order on the request path and in reverse order on the response path; each one can pass the message on, mutate it, or answer the client directly.
WASM filter. You write a plugin in Rust with the Arion SDK, compile it to a .wasm module, and reference the file from config. Arion runs it in-process on the embedded Wasmtime engine — sandboxed, with instances pooled and reused across requests. Calls into the module are function calls, not network traffic. See WASM filters.
External processing (ext_proc). Arion streams request and response phases over a bidirectional gRPC stream to a service you run anywhere, in any language. Your processor returns mutations or an immediate response. Full control, at the cost of a network hop per processed message. See External processing.
Native filter. A Rust filter compiled into Arion itself — the mechanism behind the built-in filters. It has zero serialization overhead and full access to internals, but shipping one means contributing to Arion and rebuilding the binary. See Native HTTP filters.
Comparison
| WASM filter | ext_proc | Native filter | |
|---|---|---|---|
| Runs | In-process, sandboxed | Separate service | In the binary |
| Language | Rust (SDK) | Any with gRPC | Rust |
| Overhead | In-process calls | gRPC hop per message | None added |
| Body access | Full, buffered | Streamed or buffered | Full |
| Deploy | Ship a .wasm file + config | Deploy your service | Rebuild Arion |
| Per-route | Disable only | Disable or override | Filter-specific |
| Pick when | Custom logic close to the wire | Existing code, any language, heavy logic | Core features for everyone |
Policy is configuration, not extension
Do not write a plugin for authentication or authorization that Arion already ships: JWT validation, RBAC, and Cedar policies are built-in filters you configure. Reach for an extension only when no built-in filter expresses your rule.
MCP code mode runs agent-written TypeScript inside Arion too, but it is not an extension point. Its scripts can only call the gateway's tools, and they never see or change the requests passing through the proxy.
Key terms
- Filter chain — the ordered list of HTTP filters a request passes through; see the filter chain.
- Plugin — a
.wasmmodule implementing the SDK'sPlugintrait, loaded by thewasmfilter. - Processor — your gRPC service implementing the ext_proc protocol.
- Filter decision — what a filter returns: continue, re-route, or answer the client directly.
Next
Start with WASM filters for the operator view, the Rust SDK to write one, or External processing if your logic lives in another language or service.