AWS Basics #3: Cost Management — Billing Alerts, Cost Explorer, Free Tier

10 min read

After #1 and #2 you’re ready to build something in the console. But there’s one more thing you must do first.

Cost alerts. The most common incidents go like this:

  • A NAT Gateway you spun up for learning runs all month → $45
  • A single-AZ RDS you left up for a week → $30
  • An EC2 in another region that never showed up on your radar → $80 for the month
  • Logs flooded for a month → CloudWatch $120

Every one of these was preventable if billing alerts and Budgets had been set up. This post pulls together the settings you must turn on right after signup, plus the cost-analysis tools you’ll lean on once you’re in production.

Free Tier — what’s free, and how much #

A new account gets a one-year / lifetime free allowance. The ones you’ll actually touch:

ServiceLimitPeriod
EC2t2.micro / t3.micro 750 hours / month1 year
RDSdb.t3.micro 750 hours / month, 20 GB SSD1 year
S35 GB storage + 20K GET + 2K PUT1 year
Lambda1M invocations / monthLifetime
DynamoDB25 GB + 25 RCU / WCULifetime
CloudFront1 TB egress + 10M requestsLifetime
CloudWatch10 metrics + 10 alarms + 5 GB logsLifetime
Data transfer100 GB / month to internetLifetime

Key points:

  • 750 hours / month — a month is 720–744 hours, so it’s enough to run one instance 24/7. Running two instances at the same time will bill the second.
  • Free Tier is for new accounts only — 12 months after signup, or lifetime (depends on the service)
  • Plenty of services are not on the Free Tier — NAT Gateway, EKS, Aurora, and other expensive services bill from day one

Turn on Free Tier alerts #

Console → Billing → Free Tier → “Free Tier usage alerts,” register your email.

Setup
Billing Console → Billing preferences
[✓] Receive Free Tier Usage Alerts → enter email
[✓] Receive Billing Alerts (for CloudWatch alarms)
[✓] Receive PDF invoices via email

Save and you’ll get a notification at 85% of the Free Tier. That’s your first line of defense.

Budgets — the home base of cost alerts #

CloudWatch Billing Alarms exist too, but AWS Budgets is the standard tool for billing alerts. More flexible and slices into multiple dimensions.

First budget — $10 alert #

Standard for learning / personal accounts:

Create the first budget
Console → Billing → Budgets → Create budget
- Budget type: Cost budget
- Period: Monthly
- Amount: $10 (your tolerance ceiling)
- Alert thresholds: 50%, 80%, 100% — three tiers
- Email: your email

With three tiers:

ThresholdMeaning
50% (e.g., $5)“Halfway already — what’s running?”
80% (e.g., $8)“Genuinely time to inspect”
100% (e.g., $10)“Over budget. Clean up immediately.”

Other kinds of budgets #

KindWhat it is
Cost budgetTotal cost — the most common
Usage budgetUsage like “EC2 100 hours”
RI / SP coverage budgetReserved Instance / Savings Plan utilization coverage
RI / SP utilization budgetReserved-resource utilization (is it idle?)

Starting out, one Cost budget plus 50/80/100 alerts is enough.

Slicing a budget into multiple dimensions #

A tool that helps in production.

Narrowing with filters
- By service: Amazon EC2 / RDS / Lambda only
- By tag: env=prod only
- By region: ap-northeast-2 only
- By account (on top of Organizations): prod account only

Tag-based filtering only works if tags are consistent — see the tag-strategy section below.

CloudWatch Billing Alarm — the secondary option #

The older tool that predates Budgets, still useful. Differences:

BudgetsCloudWatch Alarm
LocationBilling consoleCloudWatch (#7)
NotificationsEmail / SNS / LambdaSNS / Auto Scaling / EC2 actions
EvaluationDaily, ~8 hr lagOnce daily (us-east-1 only)
Multi-dimensionalYesSimple

In production Budgets is the standard. Reach for CloudWatch Billing Alarms when you need automated actions (e.g., alert → Lambda → terminate some resources).

CloudWatch Billing metrics live only in us-east-1. Try to create them in another region and you won’t see them.

Cost Explorer — slicing the bill #

Cost Explorer is the tool that splits your spend by time / service / tag / region and shows it in graphs. The tool you’ll use most in production.

First activation takes about 24 hours (history collection).

Initial activation
Billing Console → Cost Explorer → "Launch Cost Explorer"

Once on, you can answer the following in 30 seconds.

Q1) “Where did I spend the most this month?” #

Group by → Service — totals by service.

A typical production bill
EC2-Other (NAT, EBS)   38%
EC2 instances          22%
RDS                    15%
CloudFront             8%
S3                     6%
CloudWatch             4%
Other                  7%

Surprise #1: EC2-Other is often bigger than EC2 itself. It bundles NAT Gateway traffic, EBS volumes, and data transfer.

Q2) “Why has cost spiked since yesterday?” #

Group by → Service plus a daily bar chart. You see at a glance which service jumped. Usually one of:

  • A new resource (right after a deploy)
  • Stuck NAT Gateway traffic
  • An RDS / EC2 someone created and forgot
  • A resource in another region (filter by region)

Q3) “How much does this prod environment cost per month?” #

Group by → Tag (env) — only works with tags. That’s why a tag strategy is the prerequisite of cost analysis.

Q4) “At this rate, what’s next month?” #

Cost Explorer → Forecast — AWS shows a trend-based forecast with a ±confidence interval.

Tag strategy — the prerequisite of cost analysis #

Tags are Key=Value labels attached to every resource. They affect cost analysis, policy, and automation.

Five standard tags #

Just consistently attaching these five gets production cost analysis right.

KeyExample valuePurpose
envprod / staging / devEnvironment, cost
serviceapi / worker / webCost by service
teambackend / data / mobileCost / ownership by team
ownercurtis@example.comWho created the resource
cost-centerR&D / MarketingAccounting / chargeback

Activating cost allocation tags #

Just attaching tags isn’t enough. You have to enable them as “Cost Allocation Tags” so Cost Explorer / Budgets can use them as filters / groups.

Activation
Billing Console → Cost allocation tags
- Activate all five standard tags
- Data shows up after 24 hours to a few days

Enforcing tags #

You can deny resource creation when standard tags are missing, via an IAM policy.

Deny EC2 creation without env / service tags
{
  "Effect": "Deny",
  "Action": "ec2:RunInstances",
  "Resource": "arn:aws:ec2:*:*:instance/*",
  "Condition": {
    "Null": {
      "aws:RequestTag/env": "true",
      "aws:RequestTag/service": "true"
    }
  }
}

With this in place no one creates resources without tags.

Things that get expensive (checklist) #

Resources that often trip people up while learning. Once you’ve created them, be aware.

NAT Gateway — $0.045/hour #

  • Leave it for a month → ~$32 + traffic
  • Required for VPC private subnets to reach the internet
  • Usually overkill for side projects — work around with VPC endpoints or a public subnet
  • After learning, delete it without fail

Elastic IP — $0.005/hour (when not attached) #

  • Free while attached to an instance
  • Detached and forgotten → $3.6/month
  • Release unused EIPs immediately

RDS #

  • Even the smallest db.t3.micro is around $15/month (storage / IOPS extra)
  • Multi-AZ doubles the cost
  • After learning, snapshot then delete

EBS volumes #

  • Volumes can outlive the EC2 that used them, billing continuously
  • Check “Delete on termination” (for learning)
  • Unused snapshots also accumulate

EKS / OpenSearch / Aurora #

  • Hourly-expensive — don’t leave them up for learning
  • EKS is $0.10/hour per cluster ($72/month) — node cost is extra

CloudWatch Logs #

  • Ingestion ~$0.50/GB, storage ~$0.03/GB-month
  • Log floods are the most common incident — leave debug logging on for a month and you can accumulate tens of GB
  • Set retention per log group (#7)

Data transfer (egress) #

  • Internet egress — ~$0.09/GB (varies by region)
  • Cheaper through CloudFront
  • Cross-region ~$0.02/GB

Idle resources in other regions #

#1 pitfall #3 — audit every region. A handy script:

List EC2 / RDS in every region at once
for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
  echo "=== $region ==="
  aws ec2 describe-instances --region $region --query 'Reservations[].Instances[].[InstanceId,State.Name]' --output text
done

Receiving the invoice #

Get the monthly invoice as a PDF.

Email invoices
Billing Console → Billing preferences
[✓] Receive PDF invoices via email

The CFO / accounting email is a separate option (Account → Alternate Contacts → Billing).

Extra tools at production scale #

Things you meet at slightly larger scale.

ToolWhat it is
Cost CategoriesBundle costs into arbitrary groups (e.g., “checkout flow cost”)
Compute OptimizerRecommends right-sizing for over- / under-provisioned EC2 / Lambda
Trusted Advisor (Cost)Cost-saving inspections (Business / Enterprise support)
Savings Plans / RI30–70% discount in exchange for a 1- to 3-year commitment
Spot InstanceEC2 at ~70% off — for interruptible workloads
S3 Lifecycle / Intelligent-TieringAutomatically move old objects to cheaper classes

At small scale, just being aware of Spot / Lifecycle is enough.

Common pitfalls #

1) Not turning on billing alerts after signup #

The most common incident. You discover it on the next month’s bill — too late. The first step in this post: turn on something simple like $10 / $20 / $50 right after signup.

2) Idle NAT Gateway #

A NAT Gateway in a learning VPC left for a month → $32+. Once you’re done learning, delete the entire VPC (clean up dependencies).

3) Idle resources in another region #

Looking at one region selector hides everything in others. Audit periodically + block resource creation in other regions via IAM:

Block all regions except ap-northeast-2
{
  "Effect": "Deny",
  "Action": "*",
  "Resource": "*",
  "Condition": {
    "StringNotEquals": { "aws:RequestedRegion": "ap-northeast-2" }
  }
}

4) Cost allocation tags not activated #

Tags are consistent but Cost Explorer can’t filter on them — 99% of the time the tag isn’t activated, or it’s been less than 24 hours since activation.

5) Unaware of Free Tier expiry #

Twelve months after signup the bill suddenly grows. Free Tier expired. Mark the 12-month date on a calendar + Budgets will catch it.

6) “Used” vs “provisioned” — provisioned is what bills #

Stopping an EC2 stops compute charges, but EBS keeps billing. RDS will auto-start 7 days after being stopped. If you really aren’t going to use it, terminate it, or snapshot then delete.

Wrap-up #

What we covered:

  • Free Tier — 1 year / lifetime, 750 hours/month = enough for one instance 24/7
  • Right after signup: Free Tier alert + Billing alert + $10 / $20 / $50 Budget
  • AWS Budgets — Cost / Usage / RI etc. The 50/80/100% three-tier alert pattern
  • CloudWatch Billing Alarmus-east-1 only, for automated actions
  • Cost Explorer — split by service / tag / region. 24 hours after activation
  • Tag strategy — the five env / service / team / owner / cost-center. Cost-allocation activation is essential
  • Expensive items — NAT Gateway, Elastic IP (detached), RDS Multi-AZ, EBS, EKS, CloudWatch Logs flood, egress, idle resources in other regions
  • Production tools — Compute Optimizer, Savings Plans / Spot, S3 Lifecycle
  • Pitfalls — no billing alerts, idle NAT, other-region resources, tags not activated, Free Tier expiry, stop ≠ off

Next — CLI and SDK #

Working only in the console hits its limits fast. Now it’s time to do the same things in the terminal — faster, and automatable.

#4 AWS CLI and SDK setup walks through installing aws cli v2, aws configure, profile management, and where SDKs like boto3 fit. The IAM user’s access keys you created in #2 make their first appearance here.

X