Cloud bills are driven by architecture choices; engineers who understand pricing avoid nasty surprises.
AWS charges per use, along a few recurring dimensions:
- Compute time: per second or hour for instances, containers and databases; per request and GB-second for Lambda.
- Storage: per GB-month (S3, EBS, snapshots, backups), sometimes plus provisioned IOPS.
- Requests: API calls to S3, DynamoDB, SQS, API Gateway, KMS.
- Data transfer: inbound from the internet is free; outbound to the internet is charged per GB; traffic between AZs is charged in both directions; traffic between Regions is charged.
Some charges surprise people because nothing seems to be "running": NAT gateways (hourly plus per GB), public IPv4 addresses (hourly), unattached EBS volumes and old snapshots, CloudWatch Logs ingestion and indefinite retention, idle load balancers, and forgotten dev databases.
Tools:
- AWS Pricing Calculator to estimate before building.
- AWS Budgets to alert on actual or forecast spend; create one on day one.
- Cost Explorer to break spend down by service, account, Region, usage type or tag.
- Cost allocation tags (such as
team,env,project) must be activated in the billing console before they appear in reports, and only apply from then on. - Free Tier: new accounts get free-tier credits and allowances, and some services have always-free monthly amounts (for example, a million Lambda requests).
Prices differ by Region and change over time; check the pricing page for each service rather than memorising numbers.
Example
# Alert by email when forecast monthly spend exceeds 80% of $200
aws budgets create-budget --account-id 111122223333 \
--budget '{"BudgetName": "monthly-total", "BudgetType": "COST", "TimeUnit": "MONTHLY",
"BudgetLimit": {"Amount": "200", "Unit": "USD"}}' \
--notifications-with-subscribers '[{
"Notification": {"NotificationType": "FORECASTED", "ComparisonOperator": "GREATER_THAN",
"Threshold": 80, "ThresholdType": "PERCENTAGE"},
"Subscribers": [{"SubscriptionType": "EMAIL", "Address": "ops@example.com"}]}]'
# Top services last month
aws ce get-cost-and-usage --time-period Start=2026-09-01,End=2026-10-01 \
--granularity MONTHLY --metrics UnblendedCost --group-by Type=DIMENSION,Key=SERVICE \
--query 'ResultsByTime[0].Groups[].[Keys[0],Metrics.UnblendedCost.Amount]' \
--output text | sort -t$'\t' -k2 -nr | head -5
# Classic waste: volumes attached to nothing
aws ec2 describe-volumes --filters Name=status,Values=available \
--query 'Volumes[].[VolumeId,Size,VolumeType]' --output textRemember
- Bills are compute time + storage + requests + data transfer
- Cross-AZ, cross-Region and internet egress traffic cost money
- Set a budget alert immediately; use Cost Explorer and activated tags to attribute spend
- Watch idle resources: NAT gateways, IPv4 addresses, volumes, logs
Watch out for
- Leaving CloudWatch log groups on 'never expire' retention.