Extensions
Synapse exposes four extension points. Each sits at a different stage of the authorization request lifecycle and addresses a different integration problem. Choosing the correct type is the first step when adding a capability to Synapse.
This page summarises the four types, the integration shape each one addresses, and the implementation options available across them. Each section links to the corresponding configuration reference.
Proxy extensions
Proxy extensions intercept CheckResources and PlanResources requests travelling through Synapse, and the corresponding responses on the way back. They can add, modify or remove attributes on the principal and resources before the PDP evaluates the request, and they can rewrite or redact fields on the response before it reaches the caller. Calling applications keep using the standard Cerbos API — the enrichment happens transparently.
Proxy extensions suit integrations of the form: look up data, attach it to the request, hand the request to the PDP. Common examples:
-
Fetching a principal’s department, team, region or tier from an internal directory or IAM service.
-
Loading resource metadata (owner, sensitivity, project) that is not carried in the API call.
-
Redacting sensitive fields from
outputsblocks before they reach untrusted callers. -
Attaching audit context (tenant, trace ID, correlation ID) that downstream systems will index on.
See Proxy extensions.
Route extensions
Route extensions register custom HTTP endpoints under Synapse’s `/ext/ path and translate their requests into Cerbos authorization calls. They exist because many systems — API gateways, query engines, message queues, legacy apps — know how to delegate authorization to an HTTP endpoint, but each expects its own request and response shape.
Route extensions suit third-party systems that already delegate authorization over HTTP but expect a protocol other than Cerbos’s. Common examples:
-
Plugging Trino, Kafka, or a custom gateway into Cerbos without modifying the upstream client.
-
Exposing a simplified "can-this-user-do-that" endpoint to internal tooling.
-
Running multiple translation layers at once — each on its own
/ext/path — from the same Synapse instance.
See Route extensions.
Envoy extension
The Envoy extension implements the Envoy external authorization API natively, so an Envoy proxy (or any Envoy-based ingress like Gloo, Contour, or Istio’s filter chain) can delegate authorization decisions to Synapse without a translation layer. The mapping from Envoy’s CheckRequest to Cerbos’s request is configured declaratively or programmatically on Synapse, not in Envoy.
The Envoy extension applies when authorization must happen at the edge or inside a service mesh, and the data plane already terminates at Envoy.
See Envoy extension.
Data sources
Data sources are not wired into the request path directly. They are reusable, named lookup functions that other extensions call into via a data_source_lookup() call. A single data source — say, "employees" — can be shared by a proxy extension that enriches principals, a route extension that answers custom queries, and an envoy extension that mediates service-mesh traffic.
Data sources suit cases where several extensions call into the same underlying system (a database, an external API, an LLM) and the integration should live in one place. Synapse includes a built-in sqldb data source covering SQLite, MySQL, PostgreSQL and Litestream; custom data sources can be written in any of the supported runtimes.
See Data sources.
Picking the right type
The following table maps common integration shapes to the extension type that fits best.
| Integration shape | Extension type |
|---|---|
Enrich a Cerbos request before it reaches the PDP |
Proxy extension |
Modify or redact a Cerbos response before it reaches the caller |
Proxy extension |
Expose a custom authorization endpoint for a tool that already supports HTTP-based external authz |
Route extension |
Translate a non-Cerbos authorization protocol into a Cerbos decision |
Route extension |
Authorize Envoy traffic via its external authorization filter |
Envoy extension |
Share a database or API lookup across multiple other extensions |
Data source |
Cache or deduplicate lookups that every application would otherwise do |
Proxy extension calling into a data source |
If more than one row applies, start with the type closer to the top.
Execution model
Proxy extensions execute as a pipeline
Multiple proxy extensions can be configured against a single Synapse instance. On the request side, they execute in descending order of the priority field. On the response side, they execute in reverse. Each extension receives the request (or response) as produced by the preceding extension, so one extension can enrich the principal, another can attach resource metadata, and a third can add audit context, with each seeing the output of those that ran before it.
A failure inside an extension marked required: true terminates the pipeline and Synapse returns an error to the caller. Non-required extensions that fail are skipped and the pipeline continues with the unmodified request.
See Proxy extensions for the full priority and failure semantics.
Extensions calling the PDP bypass the proxy pipeline
When an extension calls cerbos.check_resources() or cerbos.plan_resources() from its own code — for example, a route extension translating a third-party protocol into a Cerbos decision — the call is routed directly to the PDP. The proxy extension pipeline does not run again for these internal calls. This prevents an infinite-loop condition where a proxy extension delegating to the PDP would re-trigger itself.
Enrichment required from inside an extension must be applied in the extension’s own code, or through a data source shared with the proxy pipeline, before the PDP call is issued.
Implementation options
Every extension type supports multiple implementation runtimes. The choice is independent of the extension type.
| Runtime | When to use | Trade-offs |
|---|---|---|
Native |
Built, distributed and supported by Cerbos. Use these whenever one of them already covers your integration — for example, the built-in |
No development work, but the set of native extensions is fixed. |
Declarative CEL mapping |
Available on route and envoy extensions. Use when the mapping between the incoming protocol and a Cerbos request can be expressed as a set of CEL expressions against request fields. |
No runtime to operate, fastest iteration. Limited to what CEL can express. |
Starlark |
Use for custom logic that is expressible in a Python-like scripting language — HTTP lookups, JSON manipulation, conditional enrichment. The Quick Start uses a Starlark proxy extension. |
No compilation step, fast iteration. Single-threaded, slower than WASM for CPU-heavy workloads, limited library ecosystem. |
WebAssembly (WASM) |
Use when you need a full programming language, an existing library ecosystem, or CPU-intensive logic. Extensions can be written in Go, Java, Python or TypeScript/JavaScript and compiled to WASM. |
Requires a build pipeline and deployment of binaries. Richer ecosystem, better performance, stronger sandboxing. |
Both Starlark and WASM extensions can call into data sources. Complex integrations are typically structured as one data source wrapping the system integration and one or more Starlark or WASM extensions handling the policy-specific logic.
See Building custom Synapse extensions for language-specific guides on writing Starlark and WASM extensions.
Next steps
-
Quick Start — write your first proxy extension in Starlark against a public test API.
-
Proxy extensions, Route extensions, Envoy extension, Data sources — configuration reference for each type.
-
Starlark and WASM — developer guides for the two custom-extension runtimes.