Cost Optimization & Billing

AWS bills for what you use, but that doesn't mean costs are automatic. Learn to understand your bill, set guardrails, and reduce spend without reducing capability.

Introduction

AWS's pay-per-use model means costs can grow silently as your system scales. A forgotten NAT Gateway, an over-provisioned RDS instance, or data transfer charges you didn't anticipate can turn a $50/month bill into $500 overnight. Cost optimization is not about being cheap, it is about running the same workload more efficiently so your budget goes further.

1. EC2 Pricing Models

On-Demand

Short-lived or variable workloads

Pay by the hour with no commitments. Highest unit price but maximum flexibility. Use for unpredictable workloads, dev/test, and anything you can turn off.

Reserved Instances

Stable, predictable baseline load (e.g., always-on RDS, base EC2 fleet)

1 or 3-year commitment in exchange for up to 72% discount. Standard RI: locked to instance type and AZ. Convertible RI: can change instance type.

Savings Plans

Steady workloads that may shift between services or instance types

Commit to a $/hour spend (not a specific instance). Compute Savings Plans apply across EC2, Lambda, and Fargate. More flexible than RIs with similar discounts.

Spot Instances

Interruptible batch processing, parallel stateless workloads

Unused EC2 capacity available at up to 90% discount. AWS can reclaim with 2 minutes notice. Ideal for fault-tolerant batch jobs, ML training, and rendering.

Practical strategy: run your baseline steady load on Savings Plans or Reserved Instances. Handle traffic spikes with On-Demand. Run batch jobs on Spot. A typical production account uses all four models for different parts of the same workload.

2. Cost Explorer

Cost Explorer is the AWS console tool for visualizing and analyzing spend. Use it to:

  • See cost trends over time (daily, monthly, yearly)
  • Break costs down by service, region, account, tag, or resource
  • Get Savings Plans purchase recommendations based on your usage history
  • Forecast next month's spend based on current usage
# Query last month costs grouped by service
aws ce get-cost-and-usage \
  --time-period Start=2026-05-01,End=2026-06-01 \
  --granularity MONTHLY \
  --metrics "BlendedCost" \
  --group-by Type=DIMENSION,Key=SERVICE \
  --query 'ResultsByTime[0].Groups[?Metrics.BlendedCost.Amount > `10`]'

# Find the top 5 most expensive services this month
aws ce get-cost-and-usage \
  --time-period Start=2026-05-01,End=2026-06-01 \
  --granularity MONTHLY \
  --metrics "UnblendedCost" \
  --group-by Type=DIMENSION,Key=SERVICE \
  --output table

3. AWS Budgets

Budgets send alerts when actual or forecasted costs exceed thresholds you define. Set one up immediately on a new account so unexpected resource creation doesn't surprise you at end of month:

# Create a monthly budget with email alert at 80% and 100%
aws budgets create-budget \
  --account-id 123456789012 \
  --budget '{
    "BudgetName": "MonthlyBudget",
    "BudgetLimit": {"Amount": "100", "Unit": "USD"},
    "BudgetType": "COST",
    "TimeUnit": "MONTHLY"
  }' \
  --notifications-with-subscribers '[
    {
      "Notification": {
        "NotificationType": "ACTUAL",
        "ComparisonOperator": "GREATER_THAN",
        "Threshold": 80,
        "ThresholdType": "PERCENTAGE"
      },
      "Subscribers": [{
        "SubscriptionType": "EMAIL",
        "Address": "you@example.com"
      }]
    }
  ]'

4. Tagging Strategy

Tags are key-value labels on AWS resources. Enable Cost Allocation Tags in the Billing console and your tags appear as dimensions in Cost Explorer. This lets you see cost by team, project, environment, or any dimension that matters to your organization:

# Tag resources at creation time for cost allocation
aws ec2 run-instances \
  --image-id ami-xxx \
  --instance-type t3.micro \
  --tag-specifications '
    ResourceType=instance,Tags=[
      {Key=Project,    Value=checkout-service},
      {Key=Env,        Value=prod},
      {Key=Owner,      Value=backend-team},
      {Key=CostCenter, Value=engineering}
    ]'

# In CDK: use Tags at the stack or app level
import aws_cdk as cdk
app = cdk.App()
stack = MyStack(app, "ProdStack")

cdk.Tags.of(stack).add("Project",    "checkout-service")
cdk.Tags.of(stack).add("Env",        "prod")
cdk.Tags.of(stack).add("CostCenter", "engineering")

Tag enforcement: use AWS Config rules or Service Control Policies (SCPs) in AWS Organizations to prevent untagged resources from being created. Untagged resources show up in Cost Explorer as "no tag" and become impossible to attribute to a team or project.

5. Compute Optimizer and Common Waste

AWS Compute Optimizer analyzes CloudWatch metrics for your EC2 instances, Lambda functions, ECS services, and EBS volumes, then recommends right-sized alternatives. Enable it with a single click and check recommendations monthly.

Idle RDS instances

Stop dev databases at night with Lambda + EventBridge (saves ~65% on dev costs)

Unused NAT Gateways

NAT Gateway charges ~$0.045/hr plus $0.045/GB. Delete ones not in use; consolidate where possible

Old EBS snapshots

Automated snapshots accumulate. Use Data Lifecycle Manager to retain only what you need

Unattached EBS volumes

When an EC2 terminates, its EBS may remain. Audit with: aws ec2 describe-volumes --filters Name=status,Values=available

Data transfer costs

Egress (out to internet) is charged; intra-region between AZs is also charged. Use VPC endpoints to keep S3/DynamoDB traffic free

Oversized Lambda memory

Lambda charges per GB-second. Use AWS Lambda Power Tuning (open-source) to find the optimal memory setting

Key Takeaways

  • On-Demand for flexibility; Savings Plans for steady compute; Spot for fault-tolerant batch jobs
  • Cost Explorer - visualize spend by service, region, or tag; use it to identify surprises and plan Reserved capacity
  • Budgets - set up immediately on any new account; alert at 80% to get warnings before you hit the limit
  • Tags - apply Project, Env, Owner, and CostCenter tags to every resource; enable cost allocation tags in Billing
  • Compute Optimizer - free service that analyzes your actual usage and recommends right-sized resources
  • Common waste - idle RDS instances, unused NAT gateways, unattached EBS volumes, and data transfer charges are the top culprits