JSON Schema Validation: Kong vs Envoy
Kong and Envoy both validate request bodies, and they do it in ways different enough that the choice affects latency, failure behaviour and who owns the schema. Kong runs a Lua plugin inside the worker; Envoy sends the request to an external processor over gRPC, or runs a WebAssembly module in-process. This page compares the two on the dimensions that matter once it is live.
Prerequisite concepts
This assumes the model in request validation and schema enforcement and the execution-model differences described in Kong vs Tyk vs Envoy for microservices.
Where the validation runs
The failure mode is the real difference
Kong’s plugin cannot be unavailable independently of the gateway — if the worker is running, validation is running. Envoy’s external processor can be down, slow, or overloaded while Envoy itself is healthy, and what happens then is a configuration decision you must make.
# Envoy 1.32+ — the two settings that define behaviour under validator failure
- name: envoy.filters.http.ext_proc
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_proc.v3.ExternalProcessor
grpc_service:
envoy_grpc: { cluster_name: validator }
timeout: 0.2s # must be well inside the route budget
failure_mode_allow: false # false: reject when the validator is unavailable
processing_mode:
request_header_mode: SEND
request_body_mode: BUFFERED
response_header_mode: SKIP
response_body_mode: NONE
A 200 ms timeout on a route with a 3 s budget sounds safe and is not, if the validator’s own p99 is 250 ms: every request then fails the validator call and the failure_mode_allow setting decides the outcome for all of them at once. Size the timeout above the validator’s tail latency, not above its median.
Comparing them on the dimensions that matter
Decision matrix
| Situation | Choose |
|---|---|
| Plain JSON Schema, tight latency budget | Kong plugin |
| Validation logic that needs a library | external processor |
| Team cannot operate another service | Kong plugin, or WASM |
| Validation must deploy without a gateway change | external processor |
| Very high request rate, small payloads | in-process, either product |
| Rules shared with a non-gateway consumer | external processor |
Gotchas and failure signals
An external processor on the request path is an upstream. It needs the same treatment as any other: a timeout below the route budget, a circuit breaker, capacity planning and its own dashboard.
Buffering happens on both, so the memory arithmetic is identical regardless of where the logic runs. The processor choice does not change the need for a size cap.
Kong’s plugin returns its own error shape, and the external processor returns whatever you write. Standardising the error body across routes is work either way, and it is worth doing once rather than per service.
A WASM module is in-process but not free. It has its own memory limit and a startup cost per worker, and a module that panics takes the request with it.
Who owns the schema, in practice
The dimension that decides this most often is not technical at all: it is which team is expected to change a validation rule and how quickly.
With the plugin model the schema lives in gateway configuration, which usually means a platform-team repository and a platform-team review. That is exactly right when validation is a platform concern applied uniformly, and it is friction when a product team needs to add an optional field on a Tuesday afternoon.
With the external processor the schema lives with the validator service, which the owning team deploys on its own cadence. That removes the friction and introduces a coordination question instead: a service that tightens its schema without telling anyone can start rejecting traffic that the gateway configuration says should be accepted, and the gateway’s own change log will show nothing at all.
Neither problem is unsolvable; both are worth deciding before the first schema ships, because retrofitting an ownership model onto forty routes is considerably harder than choosing one for the first.
Validation
- Validator latency measured at p99, and the timeout set above it
-
failure_mode_allowchosen per route and exercised with the validator stopped - Body size cap present regardless of which implementation is used
- Error body shape identical across routes and implementations
- External processor has its own dashboard, alerts and capacity plan
- Schema source of truth identified, with a CI check that it matches the service
FAQ
Which one adds less latency?
Kong, by a wide margin, because validation runs inside the worker process and costs tens of microseconds for a typical payload. Envoy’s external processor sends the buffered body to a separate service over gRPC, so the added latency is a round trip plus the validator’s own processing. WebAssembly sits in between: in-process like the plugin, but with language flexibility closer to the external processor.
What happens when an external validator is down?
Whatever failure_mode_allow says, which is why it must be set deliberately per route. False rejects traffic while the validator is unavailable; true lets unvalidated requests through. For a validator that is the only thing between the internet and an unhardened service, false is right. For one that mainly improves error messages, true is. Either way, exercise it with the validator stopped before you rely on the answer.
How should I size the external processor timeout?
Above the validator’s tail latency, not above its median, and well inside the route’s overall budget. A 200 millisecond timeout against a validator whose p99 is 250 milliseconds means a meaningful share of requests fail the call, and the failure mode then decides the outcome for all of them at once — which looks like a gateway problem rather than a timeout that was set too tightly.
Does the choice change how much memory validation needs?
No. Both implementations require the body to be buffered before it can be checked, so the memory arithmetic — payload size multiplied by concurrency — is identical. A request size cap is required regardless of where the validation logic runs, and it is the control that makes either option safe to enable.
Parent: Request Validation & Schema Enforcement
Related
- Request Validation & Schema Enforcement — the decision about what to validate before choosing where.
- Validating Requests Against OpenAPI at the Gateway — where the schema these engines execute comes from.
- Kong vs Tyk vs Envoy for Microservices — the execution models behind the latency difference.