Wasm Plugins
Wasm plugins let platform teams add custom request, response, or stream processing without rebuilding the data plane. Plugins are declared with WasmPlugin resources and executed inside the Rust data plane runtime.
Plugin Model
Section titled “Plugin Model”A WasmPlugin has four main parts:
| Part | Fields | Purpose |
|---|---|---|
| Module source | wasm.url, wasm.configMap, wasm.inline, wasm.sha256 | Locates and verifies the .wasm module. |
| Target binding | targetRefs | Binds the plugin to local Gateway API target resources. |
| Hook selection | hooks | Selects onRequest, onResponse, or onStreamChunk. |
| Sandbox limits | sandbox | Bounds memory, execution time, network, and filesystem access. |
Example
Section titled “Example”apiVersion: gateway.nantian.dev/v1alpha1kind: WasmPluginmetadata: name: request-audit namespace: nantian-demospec: wasm: url: https://example.com/plugins/request-audit.wasm sha256: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef targetRefs: - group: gateway.networking.k8s.io kind: HTTPRoute name: echo hooks: - onRequest - onResponse config: | {"mode":"audit"} sandbox: maxMemoryBytes: 67108864 maxExecutionTimeMs: 100 allowNetwork: false allowFileSystem: falseModule Sources
Section titled “Module Sources”Use wasm.url when modules are stored in an artifact repository, wasm.configMap when you want Kubernetes to own the module bytes, and wasm.inline only for small test modules. Set wasm.sha256 for supply-chain integrity whenever the source is external.
Target Binding
Section titled “Target Binding”targetRefs selects where the plugin runs. Start with a narrow target such as a single HTTPRoute, validate behavior, and then expand scope. If a target is missing or not accepted, inspect the control plane logs and the resource status.
Hook Lifecycle
Section titled “Hook Lifecycle”onRequestruns before upstream proxying and is useful for custom authentication, request validation, and request enrichment.onResponseruns before the response returns to the client and is useful for response headers, audit metadata, and response validation.onStreamChunkruns for streaming chunks and should keep execution time low.
Plugins should return quickly. Long-running or blocking behavior will increase route latency and can trip sandbox deadlines.
Sandbox Limits
Section titled “Sandbox Limits”Set explicit sandbox values for production:
maxMemoryByteslimits plugin heap usage.maxExecutionTimeMslimits hook execution time.allowNetworkshould stayfalseunless the plugin explicitly requires network access.allowFileSystemshould stayfalseunless the plugin explicitly requires filesystem access.
The data plane runtime enforces plugin loading and execution boundaries, but sandbox settings are still part of your production risk model.
Rollout Checklist
Section titled “Rollout Checklist”- Enable experimental features and verify
wasmplugins.gateway.nantian.dev. - Test the plugin against a non-critical route first.
- Pin external modules with
sha256. - Use the smallest practical
targetRefsscope. - Keep sandbox network and filesystem access disabled by default.
- Watch data plane logs and metrics for plugin load failures, rejections, and latency.
Writing a Plugin
Section titled “Writing a Plugin”Wasm plugins follow the standard WebAssembly module format and must export specific symbols that the data plane runtime invokes:
Required Exports
Section titled “Required Exports”Every plugin must export these WebAssembly symbols:
alloc(size: i32) -> i32: Allocates memory for data passed between the host and plugin. Returns a pointer to the allocated region.memory: The plugin’s linear memory instance, through which the host reads and writes data.- At least one hook function:
on_request,on_response, oron_stream_chunk.
Hook Function Signatures
Section titled “Hook Function Signatures”Each hook function receives request metadata and headers from the host:
on_request(context_ptr: i32, context_len: i32) -> i32on_response(context_ptr: i32, context_len: i32) -> i32on_stream_chunk(context_ptr: i32, context_len: i32) -> i32The context data is a JSON-encoded structure containing request or response headers, the backend target, and plugin configuration.
Return Values
Section titled “Return Values”- Return
0to allow the request to continue normally. - Return a non-zero HTTP status code to reject the request with that status. For example, returning
403rejects with HTTP 403 Forbidden. The rejection message can be set via a header in the context response.
Accessing Request Data
Section titled “Accessing Request Data”The plugin reads request headers and body through the context structure passed by the host. Response hooks receive the upstream response headers and status code. Stream chunk hooks receive individual chunk data for SSE-based streaming.
Plugin Configuration
Section titled “Plugin Configuration”The config field on the WasmPlugin resource is passed to the plugin as a JSON string at load time:
spec: config: | {"mode":"audit","log_level":"debug","allowed_roles":["admin","viewer"]}The plugin parses this JSON during initialization and can use it to control behavior without recompilation.
Hook Reference
Section titled “Hook Reference”on_request
Section titled “on_request”Executes before the request is proxied to the upstream backend. Use this hook for:
- Custom authentication and authorization checks.
- Request validation against a schema or policy.
- Header injection or modification (add tracing headers, tenant IDs, etc.).
- Early rejection of malformed or unauthorized requests.
on_response
Section titled “on_response”Executes after receiving the upstream response, before it returns to the client. Use this hook for:
- Response header manipulation (strip internal headers, add security headers).
- Audit metadata attachment.
- Response body validation or transformation.
- Rate-limit accounting and logging.
on_stream_chunk
Section titled “on_stream_chunk”Executes on each chunk of an SSE (Server-Sent Events) streaming response. Use this hook for:
- Streaming content inspection and filtering.
- Per-token processing for LLM streaming responses.
- Chunk-level metadata injection.
Keep chunk processing extremely fast. Streaming latency is amplified across every chunk, so even small delays per chunk add up quickly.
Hook Execution Order
Section titled “Hook Execution Order”When multiple hooks are specified on a single plugin, they execute in this order:
onRequest(before upstream)onResponse(after upstream, before client)onStreamChunk(per chunk, only for streaming responses)
If multiple plugins are bound to the same target, each hook type runs across all matching plugins before the next hook type begins.
Sandbox Configuration
Section titled “Sandbox Configuration”The sandbox enforces resource limits on each plugin to protect the data plane from runaway or malicious modules:
| Field | Type | Description |
|---|---|---|
maxMemoryBytes | integer | Maximum heap memory the plugin can allocate. Example: 67108864 for 64 MiB. |
maxExecutionTimeMs | integer | Maximum wall-clock time a single hook invocation may run. Example: 100 for 100 ms. |
allowNetwork | bool | Whether the plugin can make outbound network calls. Default: false. |
allowFileSystem | bool | Whether the plugin can read or write to the filesystem. Default: false. |
spec: sandbox: maxMemoryBytes: 67108864 maxExecutionTimeMs: 100 allowNetwork: false allowFileSystem: falseProduction Recommendations
Section titled “Production Recommendations”- Start with conservative limits and relax only when profiling shows need.
- Keep
allowNetworkandallowFileSystemdisabled unless the plugin’s documented requirements explicitly call for them. - Monitor plugin execution times through Wasm metrics and increase
maxExecutionTimeMsif near-limit warnings appear in logs.
Deployment
Section titled “Deployment”WasmPlugin CRD
Section titled “WasmPlugin CRD”The WasmPlugin custom resource is defined under gateway.nantian.dev/v1alpha1. After installing the CRD, verify it is registered:
kubectl get crd wasmplugins.gateway.nantian.devModule Sources
Section titled “Module Sources”Choose a module source based on your deployment workflow:
wasm.url: Pull the module from an HTTP/HTTPS artifact repository. Recommended for production when combined withsha256verification.wasm.configMap: Store the module bytes inline in a Kubernetes ConfigMap. Useful for GitOps workflows where modules are committed alongside manifests.wasm.inline: Embed the module bytes directly in theWasmPluginresource. Use only for small test modules due to resource size limits.
spec: wasm: url: https://artifacts.example.com/plugins/request-audit-v1.2.0.wasm sha256: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefTarget Binding
Section titled “Target Binding”targetRefs determines which Gateway API resources execute the plugin. Supported target kinds include HTTPRoute, GRPCRoute, and Gateway. Start with a single HTTPRoute, validate behavior, then expand scope.
Plugin Versioning and Updates
Section titled “Plugin Versioning and Updates”- Pin external modules with
sha256to ensure the exact module version is loaded. - Updating a plugin creates a new deployment cycle in the data plane. Existing in-flight requests continue with the old module until they complete.
- Test plugin updates against a canary route before rolling out to production routes.
Debugging
Section titled “Debugging”Common Errors
Section titled “Common Errors”| Error | Cause | Fix |
|---|---|---|
| Missing exports | Module does not export alloc, memory, or hook functions. | Verify the module was compiled for the Nantian Wasm ABI. |
| Execution timeout | Hook exceeded maxExecutionTimeMs. | Increase the timeout or optimize the hook code. |
| Memory exceeded | Plugin exceeded maxMemoryBytes. | Increase the limit or reduce allocations. |
| Module load failure | Invalid .wasm bytes or broken URL. | Verify module source and sha256 checksum. |
| Target not found | targetRefs points to a missing resource. | Confirm the target resource exists and is in the correct namespace. |
Log Output
Section titled “Log Output”Plugins can write diagnostic output through the data plane’s logging infrastructure. Messages appear in the data plane pod logs tagged with the plugin name and hook:
[wasm:request-audit][onRequest] processing request for /v1/chat/completions[wasm:request-audit][onRequest] audit mode: request acceptedIncrease log verbosity in the data plane configuration to see plugin-level debug messages.
Local Testing
Section titled “Local Testing”To test plugins before cluster deployment:
- Use the Nantian CLI to build a plugin skeleton with the required exports.
- Compile the plugin with the
wasm32-wasitarget. - Run the data plane locally in development mode with the plugin loaded via a test configuration.
- Send test requests and inspect log output and behavior.
For a full walkthrough, see the WASM Plugin Development Guide.
See Also
Section titled “See Also”- WASM Plugin Development Guide for a complete development walkthrough with code examples and testing patterns.
- Data Plane Architecture for how the plugin runtime integrates with the request lifecycle.
- Security And Observability for monitoring plugin health and performance.