When the high-level CRDs can't express it — patch Envoy directly. This repo uses it for real.
Your win: explain what an EnvoyFilter is, when to reach for it (and when
not to), and read this repo's Lua EnvoyFilter that rewrites auth headers inside the sidecar.
The last resort — by design
VirtualService, DestinationRule, and Gateway are abstractions over Envoy — clean,
portable, and covering the common cases. An EnvoyFilter drops below them: it
lets you patch the raw Envoy configuration directly — add an HTTP filter,
manipulate headers, run custom Lua/Wasm, tweak a listener.1
It's the escape hatch for things the high-level CRDs simply can't express.
Powerful, and fragile — use sparingly
Because an EnvoyFilter targets Envoy's internal config structure, it's tightly
coupled to the Envoy/Istio version: an Istio upgrade can silently break it when the
underlying config shape changes. It also bypasses Istio's validation. Istio's own docs call
it a break-glass tool. So: prefer VirtualService/DestinationRule; reach for EnvoyFilter only
when there's no other way — and pin your Istio version (here, 1.18.5).
An EnvoyFilter targets a point in the proxy
Every EnvoyFilter says where to patch and what to do:
context — SIDECAR_INBOUND / SIDECAR_OUTBOUND /
GATEWAY (which direction of which proxy).
match — the listener/filter/route to attach to.
patch — the operation (INSERT_BEFORE, MERGE,
…) and the config to splice in.
Anchor — the repo's Salesforce Lua filter
This repo does use EnvoyFilters — for auth-header rewriting, via Lua.
deployments/helm/libs/util/templates/_app_envoyfilter_salesforce.tpl
defines util.http.envoyfilter.salesforce — a kind: EnvoyFilter
(:5), context: SIDECAR_INBOUND
(:16), inserting an envoy.lua HTTP filter
(:26-29). Its inline Lua reads the X-Salesforce-Domain
header (:33), calls the auth service's
/auth/api/v1/exchange_named_credential_jwt, and swaps the
Authorization header before the request reaches your app — a token
exchange done in the sidecar, transparently. It's wired into every service via
util.app (_app.tpl:24). There's a sibling
util.hasura.envoyfilter that injects a Lua activity-log filter on the Hasura
sidecar.
Why this needs an EnvoyFilter
"Call an external auth service and rewrite a header mid-request" isn't something a
VirtualService or DestinationRule can do — they route and shape traffic, they don't run
custom logic on a request. That's precisely the gap EnvoyFilter fills: bespoke request
processing, pushed into the proxy so no app has to implement it. A textbook legitimate use of
the escape hatch.
Backend use case
Backend use case: this is the real lens for the Salesforce and Hasura Lua filters, where the mesh is doing behavior the usual CRDs do not express cleanly.
Common mistake
Common mistake: treating EnvoyFilter like a normal first-choice Istio abstraction instead of a powerful but fragile escape hatch.
Read this next
Istio docs — EnvoyFilter (reference)
context / match / patch, the operations, and the strong warnings about version coupling.
In plain English
Plain English: EnvoyFilter is the low-level escape hatch for patching proxy behavior directly when high-level Istio resources are not enough.
Check yourself (from memory)
Q1. You reach for an EnvoyFilter when…
Routing/TLS/canary have proper CRDs. EnvoyFilter is the last
resort for what those can't do — like running custom Lua.
Q2. The main risk of EnvoyFilter is that it…
It patches Envoy's internal config, so an Istio upgrade can
break it. Use sparingly and pin the version.
Q3. This repo's Salesforce EnvoyFilter uses Lua to…
SIDECAR_INBOUND Lua reads X-Salesforce-Domain,
calls auth, and rewrites Authorization before your app sees it.
EnvoyFilter — what, when, the risk, and the repo's use.
recall, then click to reveal
An ENVOYFILTER patches the RAW ENVOY config directly (add HTTP filters,
manipulate headers, run Lua/Wasm) — the ESCAPE HATCH for what VirtualService/DestinationRule/
Gateway can't express. Structure: context (SIDECAR_INBOUND/OUTBOUND/GATEWAY),
match (listener/filter/route), patch (INSERT_BEFORE/MERGE + config).
RISK: tightly COUPLED to the Envoy/Istio VERSION (an upgrade can silently break it), bypasses
validation — use SPARINGLY, pin the version. REPO (real use):
util.http.envoyfilter.salesforce (_app_envoyfilter_salesforce.tpl)
— SIDECAR_INBOUND Lua that reads X-Salesforce-Domain, calls auth's
token-exchange, and SWAPS the Authorization header before the app sees it (wired
via _app.tpl:24); plus a Hasura activity-log Lua filter. Legit use: bespoke
per-request logic a CRD can't do.
✅ Part 2 complete
You've followed traffic from the edge inward: the ingress Gateway (L5),
DestinationRule subsets & tom's affinity (L6), resilience
and what this repo does/doesn't tune (L7), and the EnvoyFilter escape hatch
(L8). Part 3 turns to security & observability — the mTLS/authorization
model (and this repo's deliberate opt-out), telemetry, and running the mesh.
Ready for Part 3 (mTLS, AuthorizationPolicy, observability, operations)? Or a
mock interview across Parts 1–2 — the Gateway/VS/DR split and "when to use
EnvoyFilter" are classic questions. Ask me.