intermediate 25 min read finops-cost-management Updated: July 13, 2025

Cloud Cost Control with Policy as Code: A FinOps Guide

Implement automated cost governance and FinOps principles using policy-as-code. Learn to enforce tagging, control instance sizes, and eliminate resource waste.

📋 Prerequisites

  • Basic understanding of cloud financial management (FinOps) principles.
  • Familiarity with at least one cloud provider (AWS, Azure, or GCP).
  • Experience with Infrastructure as Code (IaC) tools like Terraform.
  • Beginner knowledge of a policy engine like OPA/Rego is helpful.

🏷️ Topics Covered

FinOpsCloud Cost ManagementPolicy as CodeCost GovernanceOPARegoTagging StrategyCloud OptimizationInfrastructure as CodeAWS Cost Control

💡 From Reactive Bill Shock to Proactive Cost Governance

Traditional cloud cost management relies on after-the-fact reports and manual cleanup, often after significant budget overruns. A Policy-as-Code approach embeds cost controls directly into your development workflow, preventing waste before it happens.

Integrating Policy into the FinOps Lifecycle

Policy-as-Code provides the guardrails to automate and enforce best practices across the three phases of the FinOps lifecycle.

1️⃣ Inform (Visibility)

Policies can enforce consistent tagging (`owner`, `project`, `cost-center`) on all resources, providing the clean data needed for accurate cost allocation and showback.

2️⃣ Optimize (Savings)

Implement policies to restrict oversized instances, enforce storage lifecycle rules, and automatically terminate idle or non-compliant resources.

3️⃣ Operate (Continuous Improvement)

Use policy reports to track cost-saving trends, identify teams that need further optimization, and continuously refine your governance rules.

Practical Cost Control Policies with OPA/Rego

Here are three common policies you can implement immediately to gain control over your cloud spending. These examples assume the `input` is a Terraform plan converted to JSON.

Example 1: Enforce Mandatory Cost Allocation Tags

This policy ensures every new resource has an `owner` and `cost-center` tag before it can be created.

package finops.tagging

# Deny if any resource is missing required tags
deny[msg] {
    resource := input.resource_changes[_]
    resource.change.actions[0] == "create"

    provided_tags := object.keys(resource.change.after.tags)
    required_tags := {"owner", "cost-center"}
    
    missing_tags := required_tags - provided_tags
    count(missing_tags) > 0
    
    msg := sprintf("%s is missing required tags: %v", [resource.address, missing_tags])
}

Example 2: Restrict Expensive Instance Types

This policy prevents developers from accidentally provisioning oversized and expensive EC2 instances in non-production environments.

package finops.optimization

# Deny if a non-production instance uses an expensive family
deny[msg] {
    resource := input.resource_changes[_]
    resource.type == "aws_instance"
    
    # Check tags to determine environment
    resource.change.after.tags.environment != "production"
    
    # List of forbidden instance families for non-prod
    forbidden_families := {"p4d", "g5", "x2iezn", "u-6tb1"}
    instance_family := split(resource.change.after.instance_type, ".")[0]
    forbidden_families[instance_family]
    
    msg := sprintf(
        "Instance type '%v' from the expensive '%v' family is not allowed in non-production.", 
        [resource.change.after.instance_type, instance_family]
    )
}

Example 3: Identify Unattached (Wasted) EBS Volumes

This policy identifies costly EBS volumes that are not attached to any EC2 instance, representing pure waste. This would run against your current cloud state data, not a plan.

package finops.operate

# Find all volumes with a status of 'available' (unattached)
wasted_volumes[info] {
    some volume in input.aws_ebs_volumes
    volume.state == "available"
    # Ignore recently created volumes to avoid race conditions
    creation_time := time.parse_rfc3339_ns(volume.create_time)
    time.now_ns() > creation_time + (time.hour * 24)

    info := {
        "volume_id": volume.volume_id,
        "size_gb": volume.size,
        "region": volume.region
    }
}

# Generate a violation message for each wasted volume
violation[msg] {
    some info in wasted_volumes
    msg := sprintf(
        "Idle resource detected: EBS Volume '%v' (%v GB) in region '%v' is unattached.", 
        [info.volume_id, info.size_gb, info.region]
    )
}

Beyond Prevention: Cost Estimation in Pull Requests

A mature FinOps practice isn't just about preventing waste; it's also about making cost visible. Modern IaC platforms can provide cost estimates directly within the development workflow.

💡 Cost Visibility with Terraform Cloud

When you connect your Terraform configurations to a Terraform Cloud workspace, it can automatically run a speculative plan on every pull request. In addition to policy checks, it will comment on the PR with an estimated monthly cost impact of the proposed changes (e.g., "+$250.75/month"). This gives engineers and finance teams a clear, immediate understanding of the financial impact of their work before anything is applied.

Best Practices for FinOps Policies

💡 Key Takeaways

  • Start with Visibility: Your first policies should always be about enforcing tags. You can't optimize what you can't measure.
  • Use "Dry Runs" (Advisory Mode): Before enforcing a restrictive policy (like blocking large instances), run it in a non-blocking "audit" or "advisory" mode first to see its potential impact.
  • Tier Policies by Environment: Allow more flexibility in `development` environments and apply your strictest cost controls to `staging` and `production` by using parameterized policies.
  • Automate Notifications: When a policy is violated in a CI/CD pipeline, the feedback should be immediate and clear. For runtime violations, automatically notify the resource owner via Slack or email.
  • Review and Refine Continuously: Cost governance is not "set it and forget it." Review policy reports monthly to identify new waste patterns, refine your rules, and measure the impact of your FinOps program.