PDP Deployment Patterns
Your Policy Decision Point (PDP) runs OPA or Enterprise OPA (EOPA) and evaluates Rego. Your Policy Enforcement Point (PEP) — application code, API gateway, or service mesh — sends input and enforces the result.
EnforceAuth is the control plane: it builds bundles, publishes them to your bundle destination, and ingests decision logs. It does not sit in the runtime request path.
New to Policy as Code? Read OPA vs EOPA first, then Your Policy as Code journey for the full architecture path. This page goes deep on runtime placement (after you pick OPA or EOPA).
Quick decision tree
flowchart TD
A[Where does authorization run?] --> B{Kubernetes workloads?}
B -->|Yes, per-service policies| SC[Sidecar — Pattern A]
B -->|Yes, cluster admission only| ADM[Admission / Gatekeeper — Pattern B]
B -->|No| C{VM or bare metal?}
C -->|Yes| HA[Host agent / daemon]
C -->|No| D{Shared policy for many callers?}
D -->|Yes| CENT[Centralized PDP service]
D -->|No| E{Latency-critical in-process?}
E -->|Yes| EMB[Embedded SDK / serverless]
E -->|No| GW[API gateway or mesh integration]
| Scenario | We recommend | Typically used by |
|---|---|---|
| Kubernetes application | Sidecar | Platform teams on EKS/GKE/AKS; microservices with per-service bundles |
| VM / bare metal | Host agent | Legacy estates, lift-and-shift, few services per host |
| API gateway / mesh | Gateway integration | North-south traffic, uniform ingress authz |
| Shared authorization | Central PDP | Polyglot fleets, many small PEPs, one policy revision |
| Serverless / embedded | Embedded runtime | Go services, Lambda, strict sub-millisecond SLOs |
Why this decision matters
Authorization fails in production for predictable reasons:
- Latency — PEP and PDP too far apart on the network
- Stale policy — PDP has not yet activated the bundle EnforceAuth deployed
- Inconsistent input — each service builds a different JSON shape; replay and audit break
- Ops blast radius — one shared PDP outage affects every caller
Choosing sidecar vs agent vs centralized service is how you trade those risks off. There is no universal best answer — only what matches your platform and team.
OSS OPA vs Enterprise OPA (EOPA)
→ OPA vs EOPA — canonical decision guide (read this before picking a container image).
Default: OSS OPA for greenfield and most new teams. Choose EOPA when masking, delta bundles, or partitioning are hard requirements — not because you adopt EnforceAuth. Switching later is primarily an image and config change — not a Rego rewrite.
Sidecar vs host agent — why pick one?
Both run a separate PDP process your PEP calls over HTTP or a Unix socket. The difference is granularity.
Choose a sidecar when:
- You deploy on Kubernetes (or similar per-workload orchestration)
- Each service (or pod) may need a different bundle partition or config
- You want failure contained to one pod — not the whole host
- PEP → PDP latency should stay on localhost
Consider avoiding when you have hundreds of tiny functions with no orchestration — operational overhead per pod may outweigh benefits.
Failure behavior: A sidecar crash affects one pod; other replicas continue. Stale bundle = last activated policy until poll succeeds.
Choose a host agent when:
- You run on VMs or bare metal without per-app containers
- Multiple processes on one machine can share one PDP
- You want fewer PDP instances to patch and monitor
- You are not ready to adopt Kubernetes sidecar patterns
Consider avoiding when services on the same host need isolated policy partitions with independent upgrade cycles.
Failure behavior: Host agent outage affects all local PEPs on that machine. Typically lower ops complexity than per-pod sidecars.
Keep separate:
- OPA "management agent" — informal term for any long-running OPA that polls bundles and uploads logs. Both sidecars and host daemons are "agents" in that sense.
- EnforceAuth API keys — service identity for telemetry, not authorization of your end users.
When documentation says "configure your OPA agent," it usually means "configure your PDP process" — sidecar or host — with bundle polling and decision_logs.
This guide helps you choose where to run the PDP and how that choice affects operations, latency, and blast radius.
Terminology: agent vs sidecar vs service
Customers often use "agent" and "sidecar" interchangeably. In OPA deployments they mean different things:
| Term | What it is |
|---|---|
| Sidecar | OPA/EOPA container co-located with your app pod or process (typical in Kubernetes) |
| Host agent / daemon | OPA/EOPA running as a long-lived process on a VM or bare metal; apps call localhost or a Unix socket |
| Centralized PDP service | Shared OPA/EOPA fleet behind a load balancer; many PEPs call the same endpoints |
| Embedded SDK | OPA Go SDK (or similar) loads the bundle in-process — no separate PDP container |
| Gateway / mesh PEP | Envoy ext_authz, Istio, or API gateway plugin calls OPA on behalf of upstream services |
Regardless of pattern, the PDP still needs:
- Bundle source — poll EnforceAuth's published bundle (see PDP integration)
- Telemetry —
decision_logsand optionalstatusplugins pointed at EnforceAuth (see API keys)
Pattern comparison
| Pattern | Latency | Isolation | Ops complexity | Best when |
|---|---|---|---|---|
| Sidecar | Lowest (localhost) | Per-pod policy copy | Medium (K8s manifests) | Microservices on Kubernetes; per-service policy partitions |
| Host daemon | Low | Per-host shared PDP | Low–medium | VMs, legacy stacks, few services per host |
| Centralized service | Network hop | Shared PDP pool | Higher (scaling, HA) | Many small PEPs, uniform policy, language-agnostic HTTP |
| Embedded SDK | Lowest (in-process) | Per-process | Low code, higher coupling | Go services, Lambda with bundled policies, strict latency SLOs |
| Gateway / mesh | Adds proxy hop | Centralized at edge | Mesh/gateway expertise | North-south traffic, uniform authz at ingress |
| WASM | In-process | Per-runtime | Emerging | Edge workers, browser-adjacent runtimes |
Policy freshness: Sidecars and daemons poll bundles independently — stagger polling windows in large fleets to avoid thundering herds. Centralized services update once per poll cycle for all callers.
Blast radius: A misconfigured centralized PDP affects every caller. Sidecars limit impact to one pod (at the cost of more instances to manage).
Sidecar (Kubernetes)
The most common EnforceAuth customer pattern: one OPA/EOPA container per application pod, localhost HTTP between app and PDP.
→ Kubernetes Control Center — app sidecar setup (Pattern A) and fleet health in PDP Monitoring.
┌─────────────────────────────────────┐
│ Pod │
│ ┌──────────┐ ┌─────────────┐ │
│ │ App PEP │─────►│ OPA sidecar │ │
│ │ :8080 │ HTTP │ :8181 │ │
│ └──────────┘ └──────┬──────┘ │
└───────────────────────────┼─────────┘
│ bundle poll + decision logs
▼
EnforceAuth + S3/GCS
Illustrative pod excerpt (adapt image, resources, and secrets to your cluster):
containers:
- name: app
image: your-app:latest
env:
- name: OPA_URL
value: http://127.0.0.1:8181
- name: opa
image: openpolicyagent/opa:latest
args:
- run
- --server
- --addr=0.0.0.0:8181
- --config-file=/config/config.yaml
volumeMounts:
- name: opa-config
mountPath: /config
env:
- name: ENFORCEAUTH_URL
valueFrom:
secretKeyRef:
name: enforceauth-pdp
key: api-url
- name: ENFORCEAUTH_API_KEY
valueFrom:
secretKeyRef:
name: enforceauth-pdp
key: api-key
Mount the bundle + telemetry config.yaml from PDP integration. Use the console View Config flow after creating an API key with decisions:write.
Networking tip: PEP → PDP stays on 127.0.0.1. Only the sidecar needs egress to your bundle destination and api.enforceauth.com / api.enforceauth.dev.
Kubernetes admission control (platform governance)
Different problem from sidecars. Admission OPA gates cluster resource shape — Pod security context, required labels, disallowed images — when objects are created or updated. The PEP is the Kubernetes API server (via ValidatingAdmissionWebhook or OPA Gatekeeper), not your application.
EnforceAuth still builds bundles, ingests decision_logs, and shows admission PDPs in PDP Monitoring — but Rego input is an AdmissionReview, not an HTTP request body.
→ Kubernetes Control Center § Cluster admission — full separation, setup, and fleet tracking.
Host daemon / VM agent
Run OPA or EOPA as a systemd service (or container) on the host. Multiple app processes on the same machine share one PDP.
opa run --server --addr=127.0.0.1:8181 --config-file=/etc/opa/config.yaml
Same config.yaml as a sidecar — bundle polling plus decision_logs. Label each instance (labels.id, labels.environment) so EnforceAuth fleet views stay distinguishable.
Use when you are not on Kubernetes but want process isolation between app and PDP (vs embedding the SDK).
Centralized PDP service
Deploy a pool of OPA/EOPA replicas behind a load balancer. PEPs call https://opa.internal.example.com/v1/data/authz/allow.
Pros: One place to upgrade OPA, one bundle poll cycle, easier for polyglot PEPs (any language with HTTP).
Cons: Network latency, PDP becomes a critical shared dependency — plan for HA scaling and mTLS between PEP and PDP.
Failure behavior: Outage denies authorization for all callers until recovery or failover. Blast radius is fleet-wide; monitoring and redundancy are essential.
Run health checks on /health and monitor bundle activation via the status plugin (API keys with status:write).
Embedded SDK (in-process)
Load the bundle inside your application using the OPA Go SDK or equivalent. No separate PDP container.
Pros: Lowest latency, simplest local dev, natural fit for AWS Lambda with a baked-in bundle.
Cons: Policy reload requires app restart or custom hot-reload; decision log plugin is OPA-server-specific — you may need to emit logs from application code or run a companion agent for EnforceAuth ingestion.
EnforceAuth still builds and signs bundles the same way; your deploy pipeline downloads the bundle artifact into the app image or Lambda layer.
Gateway and service mesh
Envoy External Authorization (ext_authz) and similar filters call OPA with a transformed request object. The mesh or gateway is the PEP; OPA may run as a sidecar to the proxy or as a centralized filter service.
See OPA's Envoy integration for filter configuration. Wire bundle polling and decision logs on the OPA instance backing the filter.
Enterprise OPA (EOPA)
EOPA supports the same deployment patterns as OSS OPA. Teams often choose EOPA for:
- Decision log masking — redact PII before logs leave the PDP
- Delta bundles — smaller bundle updates at scale
- Partitioning — large multi-tenant fleets
Configuration lives in the same config.yaml; only the container image and optional EOPA-specific plugins differ.
Migrating from Styra DAS™? See Migration from Styra DAS™ / EOPA.
Choosing a pattern
On Kubernetes with per-service policies? → Sidecar
Few services on VMs? → Host daemon
Many languages, one shared policy revision? → Centralized PDP
Go/Lambda, latency-critical? → Embedded SDK
Ingress-only authorization? → Gateway / mesh
Fleet scale heuristics
| Fleet size | PDP pattern | OPA vs EOPA note |
|---|---|---|
| 1–20 PDPs | Sidecar or daemon — either works | OSS OPA is typical |
| 20–100 PDPs | Sidecar with staggered bundle polling | OSS OPA; watch full-bundle download size |
| 100+ PDPs | Sidecar + platform automation for config | Consider EOPA delta bundles if bundles are large or deploys are frequent |
| Polyglot, 50+ services | Centralized PDP cluster | OSS or EOPA; fewer poll endpoints to manage |
Regulated PII in input | Any pattern | Strong case for EOPA masking regardless of scale |
Stagger polling when many sidecars share one bundle destination — set min_delay_seconds / max_delay_seconds with jitter so deploys do not trigger simultaneous S3 downloads. See Bundle polling behavior for failure modes when storage is unreachable.
Whatever you pick, keep input shape consistent across PEPs so decision logs and replay stay useful. See Application integration.
Reference application
EACommerce is a sample e-commerce app pre-wired for EnforceAuth — use it to see a working PEP + PDP + bundle pull loop end to end.
Next
- Your Policy as Code journey
- Application integration — wire your PEP to the PDP
- PDP integration — bundles, API keys, decision logs
- API keys
- Bundle destinations