What OPA is: decoupled policy

One engine for all your rules.

Advanced12 min · lesson 1 of 12

Open Policy Agent (OPA) is a general-purpose policy engine. The idea is decoupled policy: instead of scattering authorization and validation logic through your application code, config, and pipelines, you write the rules once in a dedicated policy language and ask OPA for decisions. Anything that can produce JSON and act on a yes/no (or richer) answer can offload its policy to OPA — microservices, Kubernetes admission, CI pipelines, Terraform plans, API gateways.

The model is simple and uniform: OPA takes input (the JSON describing what you are asking about — a request, a resource, a plan) plus optional data (external facts like a list of allowed registries), evaluates your policy, and returns a decision. It does not know or care what the input represents; it just evaluates rules over JSON. That generality is why one engine and one language can govern such different systems.

How a policy decision is made
1input
JSON: the thing to judge
2data
JSON: external facts
3policy
Rego rules
4decision
allow / deny / details
OPA evaluates policy over input + data and returns a decision. The service enforces it; OPA only decides.

Why decouple policy

Centralizing policy has concrete benefits: rules live in one place, version-controlled and code-reviewed; they are testable in isolation; and they are consistent across services that would otherwise each reimplement “no public buckets” slightly differently. It also separates who writes policy (often security/platform) from who writes the app, without forcing a redeploy of the app to change a rule. Policy-as-code is to guardrails what IaC is to infrastructure.

OPA decides; it does not enforce
OPA returns a decision, but something else must act on it — Gatekeeper rejects the pod, Conftest fails the pipeline, your service denies the request. A policy that is evaluated but whose decision is ignored (logged-only, or a broken integration) enforces nothing. Always confirm the enforcement path actually blocks on a deny, not just that OPA returned one.