Contents
3 Chapter

Cost Management — Billing Alerts, Cost Explorer, Free Tier

The limits of the free tier, setting up AWS Budgets and billing alerts, how to slice the invoice with Cost Explorer, and the tag strategy that's the prerequisite for cost analysis. The guardrails that prevent first-invoice shock.

By creating a day-to-day user in Chapter 2 IAM, you’re ready to start making things in the console. But there’s one more thing you must do before you do that: set up cost alerts.

A common first-time AWS mistake looks like this: a NAT Gateway you created for learning runs all month for a $45 invoice, an RDS single-AZ you spun up briefly racks up $30 over a week, an EC2 in another Region stays invisible until the bill arrives for $80 a month, or CloudWatch logs pour in for a month and add $120. All of these were preventable. Just having billing alerts and Budgets turned on would have caught them.

This chapter is the second of the three first-setup items signposted in Chapter 1. It sorts out the settings you should turn on right after sign-up and the cost-analysis tools you need later in operations.

Free Tier — what, and how far #

A new account gets 1-year / lifetime free limits. Condensed to the commonly used ones:

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
Lambda1 million invocations / monthLifetime
DynamoDB25 GB + 25 RCU / WCULifetime
CloudFront1 TB egress + 10M requestsLifetime
CloudWatch10 metrics + 10 alarms + 5 GB logsLifetime
Data transfer100 GB / month to the internetLifetime

The key points:

  • 750 hours / month — a month is 720 ~ 744 hours, so it’s enough to run one instance 24 hours a day. Spin up two at once and one is charged extra.
  • Free tier is for new accounts only — 12 months after sign-up, or lifetime (per service).
  • Many services aren’t in the free tier — expensive ones like NAT Gateway, EKS, and Aurora are charged from the start.

Turning on free-tier limit alerts #

In the console → Billing → Free Tier → “Free Tier usage alerts,” enter an email address.

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

Save it, and an alert arrives at 85% of free-tier usage. This is the first safeguard.

Budgets — the home base of cost alerts #

There’s also a CloudWatch Billing Alarm, but AWS Budgets is the standard tool for billing alerts. It’s more flexible and can slice along multiple dimensions.

A first budget — a $10 alert #

This is the standard for a learning / personal account.

Creating a first budget
Console → Billing → Budgets → Create budget
- Budget type: Cost budget
- Period: Monthly
- Amount: $10 (your own risk-tolerance limit)
- Alert threshold: three stages of 50%, 80%, 100%
- Email: your own email

A three-stage alert works like this.

ThresholdMeaning
50% (e.g., $5)“Halfway there — what’s running?”
80% (e.g., $8)“Really need to check”
100% (e.g., $10)“Over. Clean up resources immediately”

Other kinds of budgets #

KindWhat
Cost budgetTotal cost — the most common
Usage budgetUsage like “EC2 100 hours”
RI / SP coverage budgetReserved Instance / Savings Plan coverage
RI / SP utilization budgetUtilization of reserved resources (are they idle)

At first, one Cost budget with 50/80/100 alerts is plenty.

Slicing a budget along multiple dimensions #

A tool that helps in the operational stage.

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

Tag-based slicing only works if tags are consistent. See the tag-strategy section later.

CloudWatch Billing Alarm — a secondary means #

It’s the older tool that predates Budgets, but it’s still valid. The differences:

BudgetsCloudWatch Alarm
LocationBilling consoleCloudWatch (Chapter 7 CloudWatch intro)
AlertEmail / SNS / LambdaSNS / Auto Scaling / EC2 action
EvaluationA day ~ 8-hour lagOnce a day (us-east-1 only)
Multi-dimensionalPossibleSimple

In operations, Budgets is the standard. Use the CloudWatch Billing Alarm only as a secondary option when you need an automatic action (e.g., alert → Lambda → terminate some resources).

CloudWatch Billing metrics exist only in us-east-1. If you try to make one in another Region, you won’t see it.

Cost Explorer — slicing the invoice #

Cost Explorer is a tool that slices cost by time / service / tag / Region, etc., and shows the results as graphs. It’s the most-used tool in operations. The first activation takes about 24 hours (to collect historical data).

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

After activation, you can answer questions like these in under 30 seconds.

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

View the per-service total with Group by → Service.

The shape of a common operational invoice
EC2-Other (NAT, EBS)   38%
EC2 instances           22%
RDS                     15%
CloudFront              8%
S3                      6%
CloudWatch              4%
Other                   7%

The biggest surprise is EC2-Other. It’s often bigger than EC2 proper. Inside it are NAT Gateway traffic, EBS volumes, and data transfer.

Answer 2) “Why did cost suddenly rise since yesterday?” #

With Group by → Service and a per-day bar graph, you can see at a glance which service grew. It’s usually one of the following.

  • A new resource (right after deploy)
  • Sleeping NAT Gateway traffic
  • An RDS / EC2 someone made and forgot
  • A resource in another Region (check with the Region filter)

Answer 3) “How much per month is this prod environment?” #

View with Group by → Tag (env). It only works if tags exist. This is why the tag strategy is the prerequisite for cost analysis.

Answer 4) “At this rate, how much next month?” #

In Cost Explorer → Forecast, AWS shows a trend-based forecast. It includes a ± few-percent confidence interval.

Tag strategy — the prerequisite for cost analysis #

A tag is a Key=Value label attached to every resource. It affects cost analysis, policy, and automation all at once.

The 5 standard tags #

If you attach these five consistently, operational cost analysis works properly.

KeyValue examplePurpose
envprod / staging / devEnvironment separation, cost
serviceapi / worker / webPer-service cost
teambackend / data / mobilePer-team cost / responsibility
ownercurtis@example.comWho made the resource
cost-centerR&D / MarketingAccounting / billing allocation

Activating cost allocation tags #

Simply attaching tags isn’t enough. You have to activate them as Cost Allocation Tags to use them as filters and groups in Cost Explorer and Budgets.

Activation
Billing Console → Cost allocation tags
- Set all 5 standard tags to Active
- After activation, data reflects after 24 hours ~ a few days

Enforcing tags #

You can enforce this with an IAM policy that denies creating a resource without the standard tags (the Condition pattern from Chapter 2 IAM).

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, nobody can create a resource without tags.

Commonly expensive items (checklist) #

These are resources that become traps at the learning stage. Once you create one, always keep an eye on it.

NAT Gateway — $0.045 per hour #

  • Leave it for a month and it’s about $32 + traffic.
  • Needed for a VPC’s private subnet to reach the internet.
  • Usually overkill for a side project. Work around it with a VPC endpoint or a public subnet.
  • Delete it without fail once learning is over.

Elastic IP — $0.005 per hour (when not attached to an instance) #

  • Free while attached to an instance.
  • Detach and forget it and it’s $3.6 a month.
  • Release an unused EIP immediately.

RDS #

  • Even the smallest db.t3.micro is about $15 a month (storage / IOPS separate).
  • The Multi-AZ option doubles the cost.
  • Snapshot and delete once learning is over.

EBS volumes #

  • Even after you terminate EC2, a remaining volume keeps being charged.
  • Recommend checking “Delete on termination” (for learning).
  • Unused snapshots also accumulate.

EKS / OpenSearch / Aurora #

  • Expensive per hour, so don’t leave them up for learning.
  • EKS is $0.10/hour per cluster ($72 a month) with node costs on top.

CloudWatch Logs #

  • Ingestion is ~$0.50 per GB, storage is ~$0.03 per GB-month.
  • A log flood is the most common incident. Leave debug mode on for a month and it’s tens of GB.
  • A retention setting per log group is essential (Chapter 7 CloudWatch intro).

Data transfer (egress) #

  • Traffic going out to the internet is ~$0.09 per GB (varies by Region).
  • It’s cheaper through CloudFront.
  • Cross-Region is ~$0.02 per GB.

Sleeping resources in another Region #

Like the pitfall in Chapter 1, check every Region. We recommend an automatic checking tool.

See EC2 / RDS across all Regions 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 invoices #

Receive a monthly invoice as a PDF.

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

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

Additional operational-stage tools #

Items you meet in a slightly larger operation.

ToolWhat
Cost CategoriesBundle cost into arbitrary groups (e.g., “checkout-flow cost”)
Compute OptimizerRecommends over- / under-sized EC2 / Lambda
Trusted Advisor (Cost)Cost-saving checks (Business / Enterprise support)
Savings Plans / RI30 ~ 70% discount with a 1 ~ 3-year commitment
Spot Instance~70% off EC2 price — interruptible workloads
S3 Lifecycle / Intelligent-TieringAutomatically move old objects to a cheaper class

In a small environment, just being aware of Spot and Lifecycle is plenty. Cost optimization overall is covered in earnest in Chapter 27 cost optimization.

Common pitfalls #

  • Not turning on billing alerts right after sign-up — the most common incident. By the time you find it looking at the invoice a month later, it’s already too late. As in this chapter’s first step, set even a simple threshold like $10 / $20 / $50 right after sign-up.
  • NAT Gateway’s sleeping cost — put a NAT Gateway in a learning VPC and leave it a month and it’s $32+. Once learning is over, delete the VPC itself (sorting out dependencies).
  • Sleeping resources in another Region — looking only at the console’s Region selector hides all the other Regions. Along with periodic checks, block resource creation in other Regions with an IAM policy.
Block Regions other than ap-northeast-2
{
  "Effect": "Deny",
  "Action": "*",
  "Resource": "*",
  "Condition": {
    "StringNotEquals": { "aws:RequestedRegion": "ap-northeast-2" }
  }
}
  • Not activating cost allocation tags — if you attached tags consistently but they aren’t caught as filters in Cost Explorer, 99% of the time you didn’t activate the tags or it hasn’t been 24 hours since activation.
  • Ignorance of free-tier expiry — 12 months after sign-up the invoice suddenly grows. It’s free-tier expiry. Mark 12 months on the calendar and let Budgets catch it.
  • It’s “provisioned,” not “used,” that’s charged — just stopping an EC2 halts compute cost but EBS cost continues. RDS also auto-starts 7 days after a stop. If you really won’t use it, terminate it or snapshot and delete.

Exercises #

  1. From the §“Free Tier” table, explain in one sentence why 750 hours / month is the amount to run one instance 24 hours a day, and write which side incurs extra cost when you run two t3.micros all month.
  2. Following §“A first budget,” write without looking the procedure for putting 50/80/100% alerts on one Cost budget. Connect in one sentence how this alert catches the “sleeping resources in another Region” incident from §“Common pitfalls” early.
  3. Compare the Deny policy in §“Enforcing tags” with the Condition clause in Chapter 2 IAM and explain how aws:RequestTag/... works at resource-creation time.

In short: Almost all AWS cost incidents come from sleeping resources, and right after sign-up the three of Free Tier alerts, Billing alerts, and a small Budget block prevent most of them. Budgets is the standard for billing alerts, and you slice the invoice by service, tag, and Region with Cost Explorer. The tag strategy is the prerequisite for cost analysis, and NAT Gateway, RDS Multi-AZ, and log floods are the most common cost sources.

Next chapter #

Working only in the console hits a limit fast. In the next Chapter 4 CLI and SDK, we make the same work faster and automatable from the terminal. We sort out installing aws cli v2 and aws configure, managing profiles, and using SDKs like boto3, and the access key of the user you made in Chapter 2 IAM shows up here for the first time.

X