Introduction
FinOps, or Financial Operations, is a collaborative methodology that aligns engineering, finance, and business teams to optimize cloud costs in real time. In 2026, with the explosion of AI workloads and Kubernetes, robust FinOps tooling is essential: it tracks spending by tag, forecasts overruns, and automates alerts. This intermediate tutorial guides you step by step to implement a complete stack on AWS: mandatory tagging via Terraform, Cost Explorer activation, Python scripts for advanced analysis, budgets with SNS alerts, and dashboards. Result: proven 20-30% cost reductions with granular visibility. Ideal for senior DevOps managing multi-account environments. Ready to turn your cloud bills into a strategic asset?
Prerequisites
- AWS account with IAM admin rights (or CostExplorerFullAccess + BudgetsReadOnly)
- AWS CLI v2 installed and configured (
aws configure) - Terraform v1.9+ installed
- Python 3.12+ with
pip install boto3 pandas - Basic knowledge of IaC and cloud scripting
- Access to AWS Organizations for multi-accounts (optional)
Activate Cost Explorer Using AWS CLI
#!/bin/bash
aws ce update-cost-allocation-tags-status \
--region us-east-1 \
--tag-keys Key1 Key2 Key3 \
--status ACTIVE
aws ce update-report-status \
--region us-east-1 \
--report-names COST_AND_USAGE \
--status COMPLETE
aws ce create-anomaly-subscription \
--region us-east-1 \
--subscription-name FinOpsAlerts \
--monitor-arn arn:aws:ce::123456789012:monitor/YOUR_MONITOR_ARN \
--threshold 30 \
--frequency MEDIUM
echo 'Cost Explorer activé avec tags et monitoring anomalie.'This Bash script activates cost allocation tags, validates the CUR (Cost and Usage Report), and creates an anomaly subscription with a +30% threshold. Replace ARNs and tag-keys with your values; run it once per region for immediate visibility in the AWS Cost Explorer console.
Enforce Mandatory Tags with Terraform
Tags are the foundation of FinOps: they attribute costs to projects, teams, or environments. Use Terraform to enforce tags via an IAM policy and a resource tag policy in Organizations.
Terraform for Mandatory Tags
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_organizations_policy" "finops_tags" {
name = "RequireFinOpsTags"
description = "Oblige les tags FinOps sur tous les ressources"
content = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Deny"
Action = "*"
Resource = "*"
Condition = {
Null = {
"aws:RequestTag/Environment" = "true"
"aws:RequestTag/Project" = "true"
"aws:RequestTag/Owner" = "true"
"aws:ResourceTag/Environment" = "true"
"aws:ResourceTag/Project" = "true"
"aws:ResourceTag/Owner" = "true"
}
}
}]
})
depends_on = [aws_organizations_organization.ROOT]
}
resource "aws_organizations_organization" "ROOT" {
feature_set = "ALL"
aws_service_access_principals = ["ce.amazonaws.com"]
}This Terraform module deploys an organization policy that blocks any resource creation without mandatory tags (Environment, Project, Owner). Apply with terraform init && terraform apply; it enforces FinOps adoption right from the creation of EC2, S3, etc., preventing orphan costs.
IAM Policy for FinOps Access
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ce:Get*",
"ce:Describe*",
"ce:List*",
"ce:CreateReport",
"ce:UpdateReport",
"budgets:ViewBudget",
"budgets:Describe*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"organizations:Describe*",
"organizations:List*"
],
"Resource": "*"
}
]
}Attach this JSON policy to an IAM role/group via console or CLI (aws iam create-policy). It provides read-only access to Cost Explorer and Budgets, ideal for FinOps analysts without modification risks.
Create a Budget with SNS Alerts
AWS budgets automate alerts on thresholds. Pair them with SNS to notify Slack/Teams.
Terraform for Budget and SNS
resource "aws_sns_topic" "finops_alerts" {
name = "FinOpsAlertsTopic"
}
resource "aws_sns_topic_subscription" "email" {
topic_arn = aws_sns_topic.finops_alerts.arn
protocol = "email"
endpoint = "finops@entreprise.com"
}
resource "aws_budgets_budget" "monthly" {
budget_type = "COST"
limit_amount = "5000"
limit_unit = "USD"
time_period_end = "2026-12-31_00:00"
time_unit = "MONTHLY"
cost_filter = {
TagNameValue = "Environment:Production"
}
notification {
comparison_operator = "GREATER_THAN"
threshold = 80
threshold_type = "PERCENTAGE"
notification_type = "FORECASTED"
sns_topic_arn = aws_sns_topic.finops_alerts.arn
}
notification {
comparison_operator = "GREATER_THAN"
threshold = 100
threshold_type = "ACTUAL"
notification_type = "ACTUAL"
sns_topic_arn = aws_sns_topic.finops_alerts.arn
}
}This Terraform code creates an SNS topic and a monthly budget filtered by 'Production' tag, with alerts at 80% forecasted and 100% actual. Integrate into main.tf and apply; emails arrive instantly on overrun.
Python Script for Detailed Cost Analysis
import boto3
import pandas as pd
from datetime import datetime, timedelta
ce = boto3.client('ce', region_name='us-east-1')
# Période : dernier mois
end = datetime.now()
start = end - timedelta(days=30)
response = ce.get_cost_and_usage(
TimePeriod={'Start': start.strftime('%Y-%m-%d'), 'End': end.strftime('%Y-%m-%d')},
Granularity='MONTHLY',
Metrics=['UnblendedCost'],
GroupBy=[{'Type': 'TAG', 'Key': 'Project'}]
)
costs = []
for group in response['ResultsByTime']:
for g in group['Groups']:
costs.append({
'Project': g['Keys'][0],
'Cost': float(g['Metrics']['UnblendedCost']['Amount']),
'Time': group['TimePeriod']['Start']
})
df = pd.DataFrame(costs)
df.to_csv('costs_by_project.csv', index=False)
print(df.sort_values('Cost', ascending=False))
print('Rapport exporté vers costs_by_project.csv')This standalone script uses Boto3 to query costs by 'Project' tag over 30 days, Pandas for DataFrame/CSV, and sorts by amount descending. Run python analyze_costs.py daily via cron for pro reports; scale with S3 export.
Integrate a Dashboard with CSV Export
After running the script, import the CSV into AWS QuickSight or Google Sheets to visualize: cost trends, top wasteful projects. Think of it as a cockpit dashboard for steering cloud finances.
Cron Job for Automated Analysis
#!/bin/bash
cd /path/to/scripts
python3 analyze_costs.py
aws s3 cp costs_by_project.csv s3://finops-bucket/reports/$(date +%Y%m%d).csv
# Envoi Slack si coût > seuil
COST=$(tail -1 costs_by_project.csv | cut -d, -f2)
if (( $(echo "$COST > 1000" | bc -l) )); then
curl -X POST https://hooks.slack.com/services/YOUR/HOOK \
-H 'Content-type: application/json' \
--data '{"text":"Alerte FinOps: Coût projet >1000$ !"}'
fiThis Bash script runs via crontab (0 9 * /path/to/cron-finops.sh): daily analysis, S3 upload, Slack alert on threshold. Install bc for floating-point comparisons; production-ready.
Best Practices
- Tag upfront: Block untagged resources via SCP (Service Control Policies) for 100% coverage.
- Automate reports: Cron + S3 + QuickSight for self-service dashboards.
- Segment by BU: Use AWS Organizations to isolate costs per account.
- Forecast with RI/SP: Include Savings Plans in analysis (add 'BlendedCost' metric).
- Review monthly: Allocate 1h/team for anomaly reviews.
Common Mistakes to Avoid
- Forgetting regions: Cost Explorer is per region; activate globally via CLI.
- Inconsistent tags: Standardize (e.g., 'env:prod') and use Tag Policies for enforcement.
- Overly broad IAM: Limit to CE/Budgets; audit logs for traceability.
- Ignoring forecasts: Use 'FORECASTED' budgets over 'ACTUAL' for proactivity.
Next Steps
Dive deeper with Kubecost for K8s, CloudZero, or our expert training. Explore Learni's FinOps and DevOps courses. Join the community for advanced templates!