Learn Istio - Advanced Extensibility (EnvoyFilter & WASM Proxy-WASM)
Series/Learn Istio/Episode 15
Episode 15 of 23

Learn Istio - Advanced Extensibility (EnvoyFilter & WASM Proxy-WASM)

Episode 15 goes beyond the built-in CRDs: when to safely use EnvoyFilter, building Proxy-WASM filters for custom logic, how to register them via extension providers and the Telemetry API, and examples of a header enricher and a telemetry exporter.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Istio already has many CRDs, but the real world always has special needs: adding custom headers, calling a custom authorization service, or exporting business metrics. Episode 15 covers two ways to extend the mesh: EnvoyFilter for direct patching and Proxy-WASM for custom filters running in a sandbox.

The main message of this episode: with great power comes great responsibility. Both tools must be used with discipline.

When to Safely Use EnvoyFilter

Usage Criteria

EnvoyFilter is a direct patch to Envoy configuration. Consider using it only when all of the following fail:

  • The feature was already tried with high-level CRDs (VirtualService, DestinationRule, Telemetry, AuthorizationPolicy).
  • The need was analyzed with proxy-config and proven unreachable through the public API.
  • The team understands the Envoy configuration structure for the version in use.

Risks You Must Acknowledge

EnvoyFilter is prone to breaking during Envoy upgrades because filter names, config structures, and APIs change between versions. The safety rules:

  • Install it in the istio-system namespace so it is visible as mesh configuration.
  • Limit it with match as specific as possible.
  • Include the owner and the reason in Git comments.
  • Test in staging with real traffic before touching production.
Inspect before patching
istioctl proxy-config listener productpage-abc123
istioctl proxy-config cluster productpage-abc123

istioctl proxy-config listener shows the real listener structure. Develop your EnvoyFilter from this structure, not from memory.

Proxy-WASM: Custom Filters in a Sandbox

Why WASM

Native Envoy filters must be written in C++ and compiled into the Envoy binary itself — impractical. Proxy-WASM (WASM) lets filters be written in other languages (Rust, Go, C++, AssemblyScript), compiled to WebAssembly, and loaded by Envoy at runtime inside a safe sandbox. Istio supports it through the WasmPlugin API.

Building a Simple Filter

The simplest example: a Rust filter that adds a header to the request. After compiling it to filter.wasm, register it:

WasmPlugin
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: header-enricher
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: productpage
  url: oci://registry.example.com/mesh/header-enricher:v1
  phase: AUTHN
  pluginConfig:
    headerName: x-tenant
    headerValue: tenant-a

WasmPlugin registers a WASM module and applies it to workloads matching the selector. The url: oci:// loads the module from an OCI registry — the recommended pattern because it can be versioned like an image.

WASM Advantages over EnvoyFilter

  • The module is sandboxed: a filter crash does not take down Envoy.
  • Module updates without rebuilding Envoy: just change the OCI version.
  • Developed in a safer language than C++ patches.

Examples: Header Enricher and Telemetry Export

Telemetry API with Extensions

Besides WasmPlugin, extensions can be attached through the Telemetry API with custom metrics:

Custom metrics via Telemetry
apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
  name: custom-metrics
  namespace: istio-system
spec:
  metrics:
  - providers:
    - name: prometheus
    overrides:
    - match:
        metric: REQUEST_COUNT
      tagOverrides:
        tenant:
          value: "istio_attributize(request.headers['x-tenant'])"

tagOverrides adds a tenant dimension to the request count metric from a header. The result: you can measure per-tenant traffic right in Prometheus — a practical example of a telemetry exporter without writing a new filter.

Extension Providers and Orchestration

When you have many WASM modules, register providers through MeshConfig extensionProviders so they can be used consistently:

Extension provider
spec:
  meshConfig:
    extensionProviders:
    - name: tenant-ext
      wasm:
        url: oci://registry.example.com/mesh/tenant-ext:v1
        imagePullPolicy: IfNotPresent

This provider can then be referenced from multiple WasmPlugins. Manage versions here, not in each plugin — it is easier to upgrade and audit.

Warning

WASM still must be tested against the Envoy version used by Istio. A module compiled for a different proxy-wasm ABI can fail to load silently. Check the istio-proxy logs on first load.

Summary

Episode 15 opened the door to extensibility: using EnvoyFilter with strict criteria and safeguards, building sandboxed and OCI-versioned Proxy-WASM filters, and integrating them through WasmPlugin, extension providers, and the Telemetry API.

Key takeaways:

  • EnvoyFilter only after high-level CRDs are proven insufficient.
  • Always develop EnvoyFilter from proxy-config output, not from memory.
  • Proxy-WASM runs in a sandbox and can be updated without rebuilding Envoy.
  • WasmPlugin is the Istio API for loading WASM modules.
  • oci:// URLs allow module versioning like images.
  • The Telemetry API can add metric dimensions without a custom filter.
  • Check the sidecar logs on the first WASM module load.

In the next episode, episode 16, we will unite many clusters: multi-cluster and mesh federation — primary-remote and replicated control plane topologies, the east-west gateway, cross-cluster service export, and establishing trust domains between meshes.

Learn Istio - Advanced Extensibility (EnvoyFilter & WASM Proxy-WASM) | Learn Istio