DevOps & Platform

Terraform for FinOps: Tagging Standards That Actually Get Enforced

5 min read

Tagging standards fail 90% of the time because they are not enforced at the Terraform layer. Here is the pattern that actually sticks across hundreds of resources and dozens of contributors.

The 4-Layer Enforcement Pattern

  1. 01Define a single source of truth: a tags module

    One Terraform module computes the canonical tag set. Every resource imports it.

  2. 02Validate at plan time with custom Sentinel/OPA policy

    Block plans missing required tags before they reach apply.

  3. 03Enforce at the AWS account level with SCPs

    Deny resource creation without tags using IAM conditions.

  4. 04Drift-detect with daily Lambda + Slack

    Catch hand-created resources that bypassed Terraform.

5-Lever FinOps FrameworkFrom audit to optimization — week-by-week01RightsizingEC2 + RDSnWeek 1–202CommitmentsSavings PlansnWeek 303Idle AuditEBS, EIPs, NATnWeek 3–404Data TransferVPC EndpointsnWeek 5–705Cost AllocationPer-customernWeek 8–10Result: 38% cost reduction · $420K annualized savings · 99.97% uptimeReal engagement · B2B SaaS · 90 days
The 5-lever framework Ohveda used to cut a B2B SaaS client’s AWS bill by 38% in 90 days.

The Tag Module

variable "service" { type = string }
variable "team"    { type = string }
variable "env"     { type = string }
variable "cost_center" { type = string }

locals {
  required_tags = {
    Service     = var.service
    Team        = var.team
    Env         = var.env
    CostCenter  = var.cost_center
    ManagedBy   = "terraform"
    Provisioner = "ohveda-tags-v3"
  }
}

output "tags" { value = local.required_tags }

The OPA Policy

package terraform.tags

required := {"Service", "Team", "Env", "CostCenter"}

deny[msg] {
  resource := input.resource_changes[_]
  not resource.change.after.tags
  msg := sprintf("%s missing tags entirely", [resource.address])
}

deny[msg] {
  resource := input.resource_changes[_]
  tags := resource.change.after.tags
  missing := required - {k | tags[k]}
  count(missing) > 0
  msg := sprintf("%s missing required tags: %v", [resource.address, missing])
}

Ready to optimize your cloud or AI footprint?

Book a free 30-minute architecture review. We will deliver a written cost-and-architecture audit within 48 hours.

Book a free architecture review · sales@ohveda.com

Need help with Terraform tagging FinOps?

Ohveda runs free 30-minute architecture reviews. We will identify your top opportunities in writing within 48 hours — at no cost.

Book a Free Architecture Review →