Skip to main content

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]
ScenarioWe recommendTypically used by
Kubernetes applicationSidecarPlatform teams on EKS/GKE/AKS; microservices with per-service bundles
VM / bare metalHost agentLegacy estates, lift-and-shift, few services per host
API gateway / meshGateway integrationNorth-south traffic, uniform ingress authz
Shared authorizationCentral PDPPolyglot fleets, many small PEPs, one policy revision
Serverless / embeddedEmbedded runtimeGo 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:

TermWhat it is
SidecarOPA/EOPA container co-located with your app pod or process (typical in Kubernetes)
Host agent / daemonOPA/EOPA running as a long-lived process on a VM or bare metal; apps call localhost or a Unix socket
Centralized PDP serviceShared OPA/EOPA fleet behind a load balancer; many PEPs call the same endpoints
Embedded SDKOPA Go SDK (or similar) loads the bundle in-process — no separate PDP container
Gateway / mesh PEPEnvoy ext_authz, Istio, or API gateway plugin calls OPA on behalf of upstream services

Regardless of pattern, the PDP still needs:

  1. Bundle source — poll EnforceAuth's published bundle (see PDP integration)
  2. Telemetrydecision_logs and optional status plugins pointed at EnforceAuth (see API keys)

Pattern comparison

PatternLatencyIsolationOps complexityBest when
SidecarLowest (localhost)Per-pod policy copyMedium (K8s manifests)Microservices on Kubernetes; per-service policy partitions
Host daemonLowPer-host shared PDPLow–mediumVMs, legacy stacks, few services per host
Centralized serviceNetwork hopShared PDP poolHigher (scaling, HA)Many small PEPs, uniform policy, language-agnostic HTTP
Embedded SDKLowest (in-process)Per-processLow code, higher couplingGo services, Lambda with bundled policies, strict latency SLOs
Gateway / meshAdds proxy hopCentralized at edgeMesh/gateway expertiseNorth-south traffic, uniform authz at ingress
WASMIn-processPer-runtimeEmergingEdge 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 sizePDP patternOPA vs EOPA note
1–20 PDPsSidecar or daemon — either worksOSS OPA is typical
20–100 PDPsSidecar with staggered bundle pollingOSS OPA; watch full-bundle download size
100+ PDPsSidecar + platform automation for configConsider EOPA delta bundles if bundles are large or deploys are frequent
Polyglot, 50+ servicesCentralized PDP clusterOSS or EOPA; fewer poll endpoints to manage
Regulated PII in inputAny patternStrong 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