Skip to main content

PEP wiring: sidecar versus centralized PDP

Objective

Compare the two common PEP-to-PDP topologies, a co-located sidecar and a centralized shared PDP, and pick one for a given constraint, naming the trade-off you accepted.

Concept

The AuthZEN contract is the same wherever the PDP runs. What changes with topology is latency, failure blast radius, and how fast a policy change reaches enforcement. Two patterns cover most deployments.

Sidecar PDP

Run an OPA (with opa-authzen-plugin) next to each service instance, in the same pod or host. The PEP calls POST /access/v1/evaluation over loopback.

flowchart LR
subgraph Pod A
A[App + PEP] -->|localhost| OA[OPA sidecar]
end
subgraph Pod B
B[App + PEP] -->|localhost| OB[OPA sidecar]
end
Writ[Writ control plane] -.signed bundle.-> OA
Writ -.signed bundle.-> OB

Text version: each application pod carries its own OPA sidecar; the PEP talks to it over localhost; the Writ control plane pushes the same signed bundle to every sidecar out of band.

  • Latency: lowest. The call never leaves the host, so there is no network hop on the enforcement path.
  • Blast radius: small. One sidecar failing takes out one instance, not the fleet. There is no shared PDP to become a single point of failure.
  • Consistency: eventual. Each sidecar loads its own copy of the bundle, so during a rollout some instances decide on the new policy and some on the old until every sidecar has pulled the update.
  • Cost and ops: you run many PDP processes. Resource use scales with instance count.

Centralized PDP

Run a PDP as its own service (or a small pool behind a load balancer). Every PEP calls the shared endpoint over the network.

flowchart LR
A[Service A + PEP] -->|network| LB[PDP service]
B[Service B + PEP] -->|network| LB
C[Service C + PEP] -->|network| LB
Writ[Writ control plane] -.signed bundle.-> LB

Text version: several services each hold a PEP that calls one shared PDP service over the network; Writ pushes the signed bundle to that PDP.

  • Latency: higher. Every decision is a network round trip. Real deployments cushion this with short-lived caching at the PEP where the policy allows it.
  • Blast radius: larger. If the shared PDP is unreachable, every PEP is affected at once, so you must run it highly available and decide a fail-closed or fail-open posture deliberately.
  • Consistency: stronger. One fleet of PDPs loads one bundle version, so a policy change flips closer to atomically across all callers.
  • Cost and ops: fewer PDP processes to run, one place to scale and monitor.

Choosing

  • Ultra-low-latency or strict tenant isolation per instance, and you can tolerate eventual policy consistency during rollout: sidecar.
  • You need a single, consistent decision surface and simpler operations, and you can absorb a network hop and engineer the PDP for high availability: centralized.
  • Large fleets often run both: sidecars for hot in-process checks, a centralized PDP for cross-cutting or heavier decisions.

Whichever you choose, the policy and its tests do not change, and neither does the AuthZEN request. Writ governs and promotes the same signed bundle to wherever the PDPs run, and captures decision logs for audit and replay regardless of topology.

Failure posture

Topology forces a failure decision. Fail-closed (deny when the PDP is unreachable) protects the resource but can take down a feature; fail-open (allow) preserves availability but opens the Authorization Gap during an outage. A sidecar's local failure hits one instance; a centralized PDP's failure hits everyone, which raises the stakes on that choice. Decide it explicitly and encode it in the PEP, not by accident.

Hands-on lab

The lab policy is topology-independent by design: the same decision rule answers whether it runs in a sidecar or a central service. Confirm it still passes, then reason about deployment:

git clone https://github.com/EnforceAuth/university-labs.git
cd university-labs
opa test courses/authzen-pdp-integration -v

Run it from the cloned university-labs repo. Expected: PASS: 9/9. Now answer in your notes: if you deployed this exact policy as a sidecar to 50 instances and pushed a change that tightens can_delete, why might two simultaneous requests to two instances briefly disagree, and how would a centralized PDP change that?

Check for understanding

  1. Which topology has the lower per-decision latency, and why?
  2. A shared PDP becomes unreachable. Which failure posture keeps the feature available, and what does that posture cost you in terms of the Authorization Gap?
  3. You push a policy change that removes a permission. Under which topology does the change reach every enforcement point more nearly atomically, and why?
  4. Does moving from a sidecar to a centralized PDP change the AuthZEN request the PEP sends or the policy the PDP evaluates? Explain.