Introduction
AWS cost management is crucial in 2026, as multi-region deployments and AI workloads explode budgets. Without advanced tools, bills can double in a month. This advanced tutorial guides you through automating analysis with the Cost Explorer API, setting up budgets with SNS notifications, enabling cost allocation tags, and deploying Boto3 scripts for custom reports. Imagine an automated dashboard that alerts on EC2 overruns before they hit your P&L. We start with CLI basics and build up to serverless Lambdas. By the end, you'll master workflows that typically save 20-40% on enterprise accounts. Ready to turn costs into a competitive advantage? (128 words)
Prerequisites
- AWS account with IAM permissions: CostExplorerFullAccess, BudgetsReadOnlyAccess, and budgets:CreateBudget
- AWS CLI v2 installed and configured (
aws configure) - Python 3.12+ with
pip install boto3 - Node.js 20+ for Lambda examples (optional)
- Advanced knowledge of IAM, SNS, and CloudWatch
Configure AWS CLI and Enable Cost Explorer
aws configure set region us-east-1
aws configure set output json
# Activer Cost Explorer (une fois par compte)
aws ce update-cost-allocation-tags-status \
--region us-east-1 \
--tag-keys Key1=Value1,Key2=Value2 \
--status ACTIVE
# Vérifier les tags activés
aws ce list-tags-for-cost-allocation --region us-east-1This script configures the CLI for JSON output and activates two essential cost allocation tags ('Key1', 'Key2') for segmenting costs by project/team. Activation takes 24 hours to propagate; avoid wildcards (*) that clutter queries. Always test with list-tags-for-cost-allocation to confirm.
Understanding Cost Allocation Tags
Cost Allocation Tags turn metadata into billable items. Without them, Cost Explorer lumps everything as 'untagged'. Activate them via CLI for instant granularity, then apply to EC2/S3 resources using User-Defined Tags. Think of it like an accountant categorizing receipts by department.
Create a Programmatic Budget with Notifications
#!/bin/bash
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
cat > budget.json << EOF
{
"BudgetName": "Monthly-Prod-Budget-2026",
"BudgetLimit": {
"Amount": "5000",
"Unit": "USD"
},
"PlannedBudgetLimits": {
"BudgetLimit": {
"Amount": "4500",
"Unit": "USD"
}
},
"CostFilters": {
"Service": ["Amazon EC2"]
},
"CostTypes": {
"IncludeTax": true,
"IncludeSubscription": true,
"IncludeSupport": false,
"IncludeUpfront": true,
"IncludeCommitment": true
},
"TimeUnit": "MONTHLY",
"TimePeriod": {
"Start": "2026-01-01T00:00Z",
"End": "2027-12-31T23:59Z"
},
"Notification": {
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"NotificationType": "FORECASTED",
"NotificationState": "OK"
},
"Arn": "arn:aws:sns:us-east-1:${ACCOUNT_ID}:CostAlertTopic"
}
EOF
aws budgets create-budget --account-id $ACCOUNT_ID --budget file://budget.json --cli-input-json file://budget.json
aws budgets create-notification --account-id $ACCOUNT_ID --budget-name Monthly-Prod-Budget-2026 --notification file://budget.jsonThis complete Bash script creates a monthly EC2 budget of $5000 USD with SNS alerts at 80% forecasted spend. It handles cost types (including taxes) and an annual time period. Pitfall: ensure the SNS ARN exists first, or create it to avoid 400 BadRequest errors.
SNS Integration for Alerts
Budget notifications trigger SNS, which can invoke Lambda or Slack. Set up a dedicated SNS topic (aws sns create-topic --name CostAlertTopic) before running. This makes budgets actionable, not just passive.
Python Boto3 Script for Cost Explorer Queries
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)
group_by = [
{'Type': 'DIMENSION', 'Key': 'SERVICE'},
{'Type': 'TAG', 'Key': 'Key1'}
]
metrics = [{'Expression': {'Text': 'SUM({{SERVICE}})', 'Label': 'TotalCost'}, 'Period': 'MONTHLY'}]
response = ce.get_cost_and_usage(
TimePeriod={'Start': start.strftime('%Y-%m-%d'), 'End': end.strftime('%Y-%m-%d')},
Granularity='MONTHLY',
Metrics=['BlendedCost'],
GroupBy=group_by,
Filter={'Dimensions': {'Key': 'SERVICE', 'Values': ['Amazon EC2']}}
)
# Convertir en DataFrame pour analyse
rows = []
for group in response['ResultsByTime'][0]['Groups']:
rows.append({
'Service': next((d['Value'] for d in group['Keys'] if d.startswith('SERVICE')), 'N/A'),
'TagKey1': next((d['Value'] for d in group['Keys'] if 'Key1' in d), 'N/A'),
'Cost': float(group['Metrics']['BlendedCost']['Amount'])
})
df = pd.DataFrame(rows)
print(df.sort_values('Cost', ascending=False))
df.to_csv('monthly_ec2_costs.csv', index=False)
print('Rapport exporté : monthly_ec2_costs.csv')This Boto3 script queries last month's EC2 costs by service and Key1 tag, exporting to CSV via Pandas. It uses BlendedCost for RI/SP savings. Pitfall: add Filter for scoping; without Pandas, use json.dumps for raw output.
Advanced Cost Analysis
This query segments by tags, uncovering costly silos (e.g., prod vs. dev). Run it via cron for trends. Analogy: like an IR scanner detecting thermal leaks in a data center.
TypeScript Lambda for Cost Alerts via EventBridge
import { CostExplorerClient, GetCostAndUsageCommand } from '@aws-sdk/client-cost-explorer';
import { SNSClient, PublishCommand } from '@aws-sdk/client-sns';
const ceClient = new CostExplorerClient({ region: 'us-east-1' });
const snsClient = new SNSClient({ region: 'us-east-1' });
export const handler = async (event: any) => {
const today = new Date();
const start = new Date(today.getFullYear(), today.getMonth(), 1).toISOString().split('T')[0];
const end = today.toISOString().split('T')[0];
const params = {
TimePeriod: { Start: start, End: end },
Granularity: 'DAILY',
Metrics: ['UnblendedCost'],
GroupBy: [{ Type: 'DIMENSION', Key: 'SERVICE' }],
Filter: { CostCategories: { Key: 'Key1', Values: ['Prod'] } }
};
try {
const command = new GetCostAndUsageCommand(params);
const data = await ceClient.send(command);
const totalCost = data.ResultsByTime?.[0]?.Groups?.reduce((sum, g) => sum + parseFloat(g.Metrics?.UnblendedCost?.Amount || '0'), 0) || 0;
if (totalCost > 1000) {
const snsParams = new PublishCommand({
TopicArn: process.env.SNS_TOPIC_ARN,
Message: `Alerte coûts Prod: $${totalCost.toFixed(2)} ce mois.`,
Subject: 'AWS Cost Alert'
});
await snsClient.send(snsParams);
}
return { statusCode: 200, body: `Coût total: $${totalCost.toFixed(2)}` };
} catch (error) {
console.error(error);
return { statusCode: 500, body: 'Erreur Cost Explorer' };
}
};This TypeScript Lambda, triggered by EventBridge (daily cron), queries Prod costs and sends SNS alerts if over $1000. Uses modular SDK v3. Pitfall: set SNS_TOPIC_ARN as env var; test with sam local invoke to avoid costly cold starts.
Serverless Automation
Deploy this Lambda via SAM/CDK for zero-ops monitoring. EventBridge rule: rate(1 day) on budget events. Scales to 100+ accounts via Organizations.
CloudFormation Stack for Multi-Region Budgets
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Budgets multi-régions avec SNS'
Parameters:
BudgetAmount:
Type: Number
Default: 5000
Resources:
CostAlertTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: MultiRegionCostAlerts
Ec2Budget:
Type: AWS::Budgets::Budget
Properties:
BudgetName: !Sub '${AWS::StackName}-EC2'
BudgetLimit:
Amount: !Ref BudgetAmount
Unit: USD
TimeUnit: MONTHLY
CostFilters:
Service: ['Amazon EC2']
CostTypes:
IncludeTax: true
Notification:
- ComparisonOperator: GREATER_THAN
Threshold: 85
NotificationType: ACTUAL
NotificationState: ALARM
- ComparisonOperator: GREATER_THAN
Threshold: 90
NotificationType: FORECASTED
NotificationState: ALARM
Subscribers:
- SubscriptionType: SNS
Address: !Ref CostAlertTopic
Outputs:
SnsTopicArn:
Value: !Ref CostAlertTopic
Export:
Name: !Sub '${AWS::StackName}-SnsArn'This CFN template deploys EC2 budgets with dual alerts (actual/forecasted) and integrated SNS. Parameterized for scaling. Pitfall: budgets are global; use --capabilities CAPABILITY_NAMED_IAM on deploy for SNS permissions.
Best Practices
- Limit to 5-10 tags max: too many dilute Cost Explorer queries.
- Use RI/SP via CLI:
aws ec2 describe-reserved-instances-offeringsfor 40-70% savings. - Cron Boto3 scripts: EventBridge > Lambda for zero infra.
- Organizations + Control Tower: centralize budgets for 1000+ accounts.
- QuickSight dashboards: ingest Boto3 CSVs for interactive visuals.
Common Errors to Avoid
- Forget 24h tag propagation: empty queries; wait or use RI tags.
- Filter without Dimensions: billions of results; always scope by Service/LinkedAccount.
- Budgets without Subscribers: silent alerts; validate SNS endpoint.
- Outdated SDK v2: migrate to v3 for auto-pagination in GetCostAndUsage.
Next Steps
Master AWS Savings Plans with this CLI guide. Explore FinOps via AWS Cost Optimization Hub. Join our Learni Dev AWS Advanced training for pro certifications. Integrate CUR (Cost & Usage Reports) with Athena for massive SQL queries.