LS LOGICIEL SOLUTIONS
Toggle navigation

What Is Policy As Code?

Definition

Policy as code is the practice of writing rules, like security requirements, compliance controls, or cost limits, as code that a machine can evaluate automatically, instead of writing them as a document that a person reads and manually checks against each request. The rule gets version-controlled the same way application code does, tested the same way, and run automatically at defined points in a pipeline or system, producing a clear pass or fail decision rather than a judgment call. A useful way to think about it is that the rule stops being something people are expected to remember and becomes something the system itself enforces, the same way a linter enforces a coding style instead of relying on every engineer to remember the style guide.

The reason policy as code exists is that manual policy enforcement doesn't scale and doesn't stay consistent. A written security policy that says "no S3 bucket should be publicly accessible" only works if someone remembers to check every single bucket, every single time, against that rule, and humans miss things, get tired, and interpret ambiguous wording differently from one review to the next. As the number of changes going through a pipeline grows, manual review becomes either a bottleneck that slows everything down or a rubber stamp that stops catching real problems. Organizations usually discover which of the two has happened only after an incident, when a post-mortem reveals that a rule everyone assumed was being enforced actually hadn't been checked carefully in months.

The mechanism that makes this work is a policy engine: software that takes a defined set of rules, written in a specific language, and evaluates them against real inputs, like a Terraform plan describing infrastructure about to be created, or a Kubernetes manifest describing a workload about to be deployed. The engine returns a decision (allow, deny, or a warning) along with a reason, and that decision gets wired into a pipeline so that a violation stops the deployment automatically, the same way a failing test stops a build. This is the mechanical core of the entire practice, and everything else, the language used to write rules, the specific engine that evaluates them, is really just implementation detail sitting on top of this basic input-decision-action loop.

By 2026, policy as code shows up throughout most mature infrastructure and platform engineering setups: checking Terraform plans before they apply, gating what gets admitted into a Kubernetes cluster, and enforcing rules inside CI/CD pipelines before code ever reaches production. It became standard alongside infrastructure as code, because once infrastructure changes are defined in version-controlled files, checking those files against rules written the same way is a natural next step, and skipping it leaves a gap between what a policy document says and what actually gets deployed. That gap is exactly where audits and incident investigations tend to find the most uncomfortable surprises, since a policy that only exists on paper offers no real evidence that it was actually followed.

This page covers how a policy as code check actually runs inside a real pipeline, how it compares to manual policy review, what a well-written policy rule looks like in practice, where the approach fits and where it doesn't, and how a team gets started writing and enforcing its own rules. The underlying idea is that a rule enforced by code runs the same way every time, on every change, without needing a person to remember it, which turns policy from a document into an active part of the system.

Key Takeaways

  • Policy as code expresses rules like security, compliance, and cost requirements as version-controlled code that a machine evaluates automatically.
  • It exists because manual policy review doesn't scale consistently: humans miss things, interpret rules differently, and become a bottleneck as change volume grows.
  • The mechanism is a policy engine that evaluates rules against real inputs (like infrastructure plans or deployment manifests) and returns an automatic pass, fail, or warning decision.
  • It fits naturally into CI/CD pipelines, infrastructure provisioning, and Kubernetes admission control, but fits poorly for rules that genuinely require human judgment rather than a clear pass or fail check.
  • Getting started well means picking a handful of high-value, unambiguous rules first, not trying to encode every existing policy document on day one.

How Policy as Code Actually Runs in a Pipeline

The typical entry point is a specific stage in a pipeline where something measurable is about to change: a Terraform plan showing what infrastructure is about to be created or modified, a Kubernetes manifest about to be applied to a cluster, or a pull request about to be merged. At this stage, the pipeline calls out to a policy engine, handing it the relevant input, usually as structured data (often JSON) describing exactly what's about to happen. This is a deliberately narrow scope: the engine only ever sees the specific slice of information it's given, which is part of what makes it fast and predictable, but also means the quality of a decision depends heavily on whether the input actually captures everything relevant to the rule being checked.

The policy engine evaluates that input against a set of rules written ahead of time, in a language designed for this purpose (Rego is the most common example, used by Open Policy Agent, though other tools use their own domain-specific languages). Each rule checks for a specific condition: does this Terraform plan create a security group open to the entire internet, does this Kubernetes manifest request privileged access it shouldn't have, does this resource lack a required cost-tracking tag. The engine runs through the applicable rules and returns a decision. Well-organized rule sets tend to group related checks together, security rules in one place, cost rules in another, so that a team debugging a failure doesn't have to search through an undifferentiated pile of conditions to find the one that fired.

If everything passes, the pipeline continues without any human needing to look at it, the same way a passing test suite lets a build proceed. If something fails, the pipeline stops, and the person who submitted the change gets a specific, readable explanation of what rule got violated and often a suggestion for how to fix it, ideally without needing to escalate to a security or compliance team just to understand the problem. Getting this feedback loop tight, from violation to a clear, actionable message, is often the difference between a policy engine that engineers tolerate and one they actively resent.

This runs consistently, on every single change, which is the property that manual review structurally cannot match. A policy engine doesn't skip a check because it's Friday afternoon, doesn't approve something because the requester seems trustworthy, and doesn't interpret an ambiguous rule differently depending on who's reviewing that day. The tradeoff is that the rule has to be written precisely enough for a machine to evaluate it, which is harder than it sounds for policies that were originally written as prose for a human audience. Translating a paragraph of legal or compliance language into a specific, testable condition is often the slowest part of adopting policy as code, well ahead of any actual coding work.

Policy as Code vs. Manual Policy Review

Manual policy review typically works like this: a written policy document exists, usually maintained by a security or compliance team, and changes going through some approval process get checked against that document by a person, often as one step in a broader change approval workflow. This works reasonably well at low volume, where a small number of experienced reviewers can hold the relevant rules in their heads and apply them consistently enough. It's genuinely fine at that scale, and organizations shouldn't feel behind for still relying on it while they're small.

It breaks down as volume grows, for a few concrete reasons. First, reviewer bandwidth doesn't scale with the number of changes; adding more reviewers helps only up to a point, and even experienced reviewers make different judgment calls from each other on borderline cases. Second, manual review happens at a point in the process that's often too late, catching a problem only after significant work has already gone into a change, which makes fixing it more expensive than catching it earlier would have been. Third, the review itself isn't easily auditable in a rigorous way; proving after the fact that a specific rule was actually checked, and checked correctly, on a specific change usually depends on a person's notes or memory rather than a clean, reproducible record. An auditor asking "show me evidence this rule was checked on every change in the last quarter" is a request manual review typically cannot answer with any real confidence.

Policy as code addresses all three of these directly. It scales with pipeline throughput rather than reviewer headcount, since the engine evaluates rules in milliseconds regardless of how many changes are running through it at once. It runs earlier in the process (often directly against a plan or manifest before anything gets applied), catching problems before they become expensive to fix. And it produces a clean, reproducible record automatically: exactly which rule ran, against exactly which input, with exactly which result, which is far easier to hand to an auditor than a reviewer's memory of a conversation from three months ago. This record-keeping benefit tends to surface as a strong selling point internally too, since it removes the awkward burden of a security team having to reconstruct, after the fact, what actually happened during a specific review.

The honest limitation is that policy as code only works for rules that can be expressed as a clear, checkable condition against structured data. Rules that require genuine judgment (is this vendor relationship appropriate, does this business justification make sense) don't translate into code well, and forcing them into a policy engine usually produces a rule so rigid it either blocks legitimate cases or misses the actual intent behind the original policy. Manual review doesn't disappear entirely; it moves to the smaller set of decisions that genuinely need a human, while the mechanical, checkable rules move to code. Recognizing which category a given rule falls into, checkable versus judgment-based, before trying to automate it saves a lot of wasted effort writing Rego for something that was never going to work as a rigid check.

What a Good Policy Rule Looks Like

A good policy as code rule starts from a specific, checkable condition, not a vague principle. "Infrastructure should be secure" isn't a rule a policy engine can evaluate; "no S3 bucket may have public read access enabled" is. The difference matters: a rule needs to reduce to something a machine can check against structured data and return a definite yes or no on, and writing rules at that level of specificity is most of the actual work of doing policy as code well. Teams new to this practice often spend their first few weeks just rewriting existing policy statements into this more precise form, well before touching a policy engine at all, and that rewriting exercise alone usually surfaces ambiguities in the original policy nobody had noticed.

A practical example: a rule requiring every cloud resource to carry a cost-center tag. Written as code, this rule inspects the resource definition in a Terraform plan, checks for the presence of a specific tag key, and fails the plan if it's missing, with an error message telling the requester exactly which resource is missing the tag and what value is expected. This is a small, unambiguous check, and it's exactly the kind of rule that policy as code handles well, because there's no judgment involved, just a presence check. Rules like this one are usually the best starting point for a team new to policy as code, since the effort to write them is small and the payoff (accurate cost allocation, a cleaner audit trail) is immediate and easy to point to.

A second example, slightly more involved: a rule blocking any Kubernetes deployment that requests privileged container access unless it's explicitly on an approved allowlist. This requires the policy to check the manifest for a specific field, cross-reference it against a maintained list of exceptions, and fail if the deployment isn't on that list. This is still fully checkable by a machine, but it shows that good rules often need a bit more structure than a simple presence check, including a way to handle legitimate exceptions without disabling the rule entirely. The allowlist itself becomes an artifact worth maintaining carefully, since a list that only ever grows and never gets reviewed tends to become a de facto exemption for everyone eventually, which quietly defeats the point of the rule.

The common failure mode is writing a rule that's too broad or too narrow. A rule that's too broad ends up blocking legitimate work constantly, which trains engineers to find workarounds or to ask for blanket exemptions, quietly undoing the value of having the rule at all. A rule that's too narrow only catches the exact scenario it was written for and misses close variants of the same underlying risk. Good policy as code, in practice, comes from iterating on rules based on real violations and real false positives, not from trying to write the perfect rule on the first attempt. Building a habit of reviewing rule performance on a regular cadence, monthly is common, catches both problems early, before a too-broad rule trains people to route around it and before a too-narrow one lets a real risk slip through unnoticed.

Where Policy as Code Fits and Where It Doesn't

Policy as code fits strongly anywhere a change can be represented as structured data before it takes effect: infrastructure provisioning through tools like Terraform, container orchestration through Kubernetes manifests, API gateway configuration, and CI/CD pipeline definitions themselves. In all of these cases, there's a clear artifact to check (a plan, a manifest, a config file) and a clear point in the process to check it, which is exactly the setup policy as code needs to work well. Almost anywhere infrastructure as code has already been adopted, policy as code follows naturally as the next layer, since the hard part (getting changes into a structured, machine-readable form in the first place) has already been done.

It also fits well in regulated environments, where being able to prove that a rule was checked, consistently and automatically, on every relevant change carries real weight with auditors. A policy engine's decision log is a much stronger piece of evidence than a reviewer's recollection, and organizations under real compliance pressure tend to be some of the earliest and most committed adopters of this approach for exactly that reason. A single policy engine log covering months of activity is often a faster and more convincing artifact to hand an external auditor than a stack of manually filled-out review forms ever was.

It fits poorly for decisions that require weighing context a machine doesn't have access to, like whether a particular vendor relationship makes business sense, or whether an unusual request has a legitimate reason behind it that isn't visible in the structured data being checked. Trying to force these into a policy engine usually produces something that's either too permissive to matter or too rigid to be usable, and the better answer is to keep these as manual review, ideally informed by whatever data the policy engine can still surface to help the reviewer decide faster. A useful pattern here is having the policy engine flag a request as needing review, along with the specific reasons it couldn't auto-approve, rather than trying to force a binary decision on something genuinely ambiguous.

It also fits poorly, at least initially, in organizations with no existing culture of writing rules down precisely at all. If the current state is a set of unwritten norms that live in a few experienced people's heads, jumping straight to policy as code usually stalls, because the hard work of turning vague norms into precise, checkable rules hasn't been done yet. That translation work needs to happen first, even informally, before the code-writing part becomes productive. Writing down the top handful of norms in plain language, even as a simple internal document, and getting the team to agree they're accurate is often the necessary first step that shouldn't be skipped in a rush to get to the tooling.

How to Start Writing and Enforcing Policy as Code

Start with a small number of rules that are already unambiguous and already causing real, specific pain. A common starting point is a handful of security rules everyone already agrees on (no public storage buckets, no hardcoded credentials in configuration, mandatory encryption at rest) because these have a clear right answer and a track record of causing real incidents when missed. Trying to encode an entire compliance framework on day one is a common way for these efforts to stall before delivering any value. A handful of working rules that people trust does more for long-term adoption than a comprehensive framework that's still being debugged six months after launch.

Pick a policy engine and a specific enforcement point before writing rules broadly. Open Policy Agent is a common general-purpose choice, used across infrastructure, Kubernetes, and application-level authorization, though some ecosystems have their own native tools (Sentinel for HashiCorp's stack, native Kubernetes admission controllers) that may fit more naturally depending on what's already in use. The enforcement point matters just as much as the engine: deciding whether a rule runs against a Terraform plan before apply, or against a live cluster on an ongoing basis, changes both how the rule gets written and how disruptive a failure is to the team affected. Getting this choice right up front avoids a fair amount of rework later, since moving an enforcement point after teams have already built workflows around it tends to be disruptive in its own right.

Run new rules in a warning-only mode before making them a hard block. This gives the team visibility into how often a rule would actually fire against real, current activity, without immediately breaking anyone's workflow. It's common to discover that a rule everyone assumed was reasonable actually fires constantly against legitimate cases, which is a sign the rule needs refining before it becomes a blocking gate rather than a sign that policy as code doesn't work.

Treat the rules themselves as a maintained codebase, not a one-time project. Rules need owners, need to go through the same kind of review and testing that application code does, and need to be updated as the underlying systems and requirements change. Organizations that get real, lasting value from policy as code tend to have a specific team or set of individuals responsible for maintaining the rule set, the same way there's ownership over any other piece of production code. Without that ownership, rules quietly go stale, still technically running but no longer reflecting what the organization actually wants enforced, which is arguably worse than having no automated policy at all because it creates false confidence.

Best Practices

  • Start with a small number of unambiguous, already-agreed-upon rules rather than trying to encode an entire policy framework at once.
  • Run new rules in warning-only mode first to see how often they'd actually fire before making them a hard block.
  • Write clear, specific error messages so a rule violation tells the requester exactly what to fix, not just that something failed.
  • Give the policy rule set a real owner and maintain it like production code, with review, testing, and version history.
  • Keep genuinely judgment-based decisions out of the policy engine and route them to manual review instead of forcing a rigid rule onto them.

Common Misconceptions

  • Policy as code replaces the need for a security or compliance team: it automates the checkable, repeatable parts of their work, but judgment calls still need people.
  • Any policy document can be turned into code directly: vague, principle-based policies need to be rewritten as specific, checkable conditions first, which is often the harder part.
  • Policy as code is only relevant to infrastructure teams: it applies just as well to application-level authorization, API access control, and CI/CD pipeline rules.
  • Once written, a policy rule doesn't need maintenance: rules need updates as systems, requirements, and legitimate exceptions change over time.
  • Blocking a change automatically is always the right response to a violation: warning-only enforcement is often the better starting point, especially for new or unproven rules.

Frequently Asked Questions (FAQ's)

What is policy as code?

Policy as code is the practice of writing security, compliance, or operational rules as version-controlled code that a policy engine evaluates automatically against real changes, rather than relying on manual review of a written policy document.

What languages are used to write policy as code?

Rego, used by Open Policy Agent, is one of the most common. Other tools use their own domain-specific languages, such as Sentinel for HashiCorp's ecosystem, and some platforms support policy rules written in more general-purpose languages as well.

Where does policy as code typically get enforced?

Common enforcement points include infrastructure provisioning pipelines (checking Terraform plans before they apply), Kubernetes admission control (checking manifests before they're deployed), and CI/CD pipelines (checking code or configuration before merge or release).

Is policy as code the same as Open Policy Agent?

No. Policy as code is the broader practice; Open Policy Agent is one specific, widely used tool for implementing it. Other tools and platforms also support writing and enforcing policy as code.

Can policy as code fully replace manual policy review?

No, not entirely. It handles rules that reduce to a clear, checkable condition well, but decisions requiring genuine human judgment still need manual review, often informed by data the policy engine surfaces.

How do you avoid policy as code rules blocking legitimate work?

Running new rules in warning-only mode before enforcing them as hard blocks, writing specific error messages, and iterating on rules based on real violations and false positives all help avoid this.

Does policy as code slow down deployments?

Well-written rules run in milliseconds and don't meaningfully slow a pipeline down. Rules that are poorly written or overly broad can cause delays by blocking legitimate changes, which is usually a sign the rule needs refinement.

Who should own policy as code rules within an organization?

Ownership varies, but it's usually a platform engineering, security, or compliance team, and mature organizations treat the rule set as a maintained codebase with clear ownership rather than a one-time project.

How does policy as code relate to Open Policy Agent specifically?

Open Policy Agent is one of the most widely adopted engines for implementing policy as code, providing the Rego language and the runtime that evaluates rules against structured input across infrastructure, Kubernetes, and application contexts.