Where to Run Infrastructure Policies: Plan, Apply, and Post-Deploy

You have written your infrastructure policies as code. They check for security violations, cost overruns, and naming conventions. Now comes the practical question: where in your pipeline should those policies actually run?

The answer is not one place. It is three. Each location catches a different kind of problem, and skipping any of them leaves gaps in your guardrails.

Policy at Plan Time: Catch Problems Before They Happen

The first place to run policies is during the plan phase. In tools like Terraform, Pulumi, or OpenTofu, the plan phase calculates what changes would be made to your infrastructure. It shows you a diff: resources to create, modify, or delete. But nothing has actually changed yet.

Running policies here acts as an early filter. The policy engine inspects the planned changes and decides whether they are allowed. If a developer tries to open a security group to 0.0.0.0/0, the policy blocks it at plan time. If someone selects an expensive instance type that exceeds your budget threshold, the policy flags it. If a resource name does not follow your naming convention, the policy rejects it.

The advantage is obvious: you prevent violations before any resource exists. The pipeline stops, the developer gets a clear message about what was blocked and why, and they can fix the code without having to clean up resources that were already created. No rollback needed. No orphaned resources. No security exposure window.

Here is a concrete example using Open Policy Agent (OPA) to enforce a policy that blocks public security groups at plan time:

# Generate a Terraform plan and convert it to JSON
export TF_VAR_region="us-east-1"
terraform plan -out=plan.tfplan
terraform show -json plan.tfplan > plan.json

# Evaluate the policy: deny if any security group has 0.0.0.0/0 ingress
# policy.rego contains: deny[msg] { ... }
opa eval --data policy.rego --input plan.json "data.terraform.deny"

# If the output contains a deny message, fail the pipeline
if opa eval --data policy.rego --input plan.json "data.terraform.deny" | grep -q '"result"'; then
  echo "POLICY VIOLATION: Public security group detected. Blocking deployment."
  exit 1
fi

This is the most efficient place to enforce policies. It saves time, reduces waste, and keeps your infrastructure clean from the start.

Policy at Apply Time: The Last Line of Defense

The second place to run policies is during the apply phase. Apply is when the changes actually hit your infrastructure. Resources get created, modified, or destroyed for real.

Why run policies again if you already checked at plan time? Because plan-time checks have blind spots. They only see what is in the code. They cannot see the actual state of your infrastructure, which may have drifted outside the pipeline. Someone might have changed a resource manually through the console. A previous deployment might have left things in an unexpected state. The plan assumes a certain starting point, but reality can differ.

Policy at apply time re-validates before the changes execute. It catches cases where the plan looked fine but the actual infrastructure state would cause a violation. It also handles scenarios where changes come from outside the pipeline entirely. If someone runs a manual Terraform apply from their laptop, the apply-time policy still fires.

Another important use case is approval gates. At plan time, a policy can detect a violation and flag it. But the decision to proceed or stop often happens at apply time. Maybe the violation requires a senior engineer to approve an exception. Maybe the change is high-risk and needs a second pair of eyes. Apply-time policies can enforce those workflows.

Think of plan-time policies as prevention and apply-time policies as verification. Both are needed.

Policy After Deployment: Detect Drift and Silent Violations

The third place to run policies is after resources are already running. This is post-deploy enforcement, and it serves a different purpose.

Plan and apply policies catch violations at the moment of change. But infrastructure does not stay static. Someone with console access can modify a security group rule after deployment. A new compliance requirement can make previously acceptable resources non-compliant. Resources that were supposed to be temporary might still be running months later, costing money.

Post-deploy policies run on a schedule. Every hour, every night, or every week, they scan your live infrastructure and compare it against your policy rules. Any resource that violates a rule gets reported. The report goes to Slack, email, or a dashboard. The team then fixes the violation or removes the resource.

This is how you catch configuration drift. It is also how you enforce policies that cannot be checked at plan or apply time. For example, a policy that says "no resource should be older than 90 days without review" can only be enforced by scanning running resources periodically.

Post-deploy policies turn compliance from a one-time gate into an ongoing practice. Without them, your infrastructure slowly drifts away from your standards, and nobody notices until the next audit.

How the Three Points Work Together

Each point covers what the others miss. Plan-time policies stop violations before they happen. Apply-time policies catch what plan-time missed and enforce approval workflows. Post-deploy policies detect drift and long-running issues.

The diagram below shows how the three policy checkpoints fit into a typical infrastructure pipeline:

flowchart TD A[Code Commit] --> B[Plan Phase] B --> C{Plan-Time Policy Check} C -->|Pass| D[Apply Phase] C -->|Fail| E[Block & Notify Developer] E --> A D --> F{Apply-Time Policy Check} F -->|Pass| G[Resources Created/Modified] F -->|Fail| H[Block & Require Approval] H --> D G --> I[Post-Deploy Policy Scan] I -->|Compliant| J[Monitor Continuously] I -->|Drift Detected| K[Alert Team & Remediate] K --> G

If you only run policies at plan time, manual changes bypass your rules. If you only run policies at apply time, you still create resources that violate policy before the check runs. If you only run policies after deployment, you are always reacting to problems instead of preventing them.

All three are necessary for a complete guardrail system.

Practical Checklist

Here is a quick reference for setting up policy execution points in your pipeline:

  • Plan stage: Run policies against the planned diff. Block changes that violate security, cost, or naming rules. Fail the pipeline early.
  • Apply stage: Run policies again before executing changes. Catch drift and enforce manual approval for high-risk changes.
  • Post-deploy: Schedule periodic policy scans of live infrastructure. Report violations to the team. Fix or remove non-compliant resources.

The Takeaway

Running policies in one place is not enough. Plan-time checks prevent problems before they start. Apply-time checks catch what slips through. Post-deploy checks keep your infrastructure honest over time. Build all three into your pipeline, and your policies will actually protect your infrastructure instead of just giving you a false sense of security.