Module 4 · Cloud Fundamentals: Cost, Scaling and Reliability
Idle and forgotten resources
Find the resources that cost money while doing nothing (idle servers, unattached disks, unused IP addresses, old snapshots and the disks of stopped servers) and plan their removal safely.
About 25 minutes
The problem
In the cloud, nothing is ever thrown away by accident. A server created for a load test in 2025 keeps running until someone deletes it. When a server is deleted, its disk can stay behind, still billed every hour. Backups (snapshots) pile up for years.
Nobody at Tallybook did anything wrong on any single day. Forgotten resources are what happens when creating things is easy and nobody's job is to clean up. They're also the easiest savings in any cloud bill, because removing them changes nothing that anyone uses.
The concept
Common kinds of waste
| Waste | How to spot it |
|---|---|
| Idle servers | running, but CPU near zero for weeks |
| Unattached disks | status "unattached": their server is gone |
| Stopped servers | no compute charge, but their disks are still billed |
| Unused IP addresses | reserved public IPs attached to nothing are charged |
| Old snapshots | backups kept far longer than any policy requires |
Remove safely
- Find an owner (tags, names, creation history), and ask.
- If nobody claims it: snapshot then delete for disks; stop, wait, then delete for servers.
- Set a retention policy (for example, keep snapshots 90 days), and apply it automatically.
Example
import pandas as pd
base = "https://academy.cloudtechanalytics.com/datasets/cloud/"
resources = pd.read_csv(base + "resources.csv", parse_dates=["created_date"])
util = pd.read_csv(base + "utilisation.csv")
TODAY = pd.Timestamp("2026-09-01")
HOURS_PER_MONTH = 730
cpu_max = util.groupby("resource_id")["cpu_pct"].max()
resources["cpu_max"] = resources["resource_id"].map(cpu_max)
stopped_ids = resources.loc[(resources["type"] == "vm") & (resources["status"] == "stopped"), "resource_id"]
waste = pd.concat([
resources[(resources["type"] == "vm") & (resources["cpu_max"] < 5)].assign(reason="idle server"),
resources[(resources["type"] == "disk") & (resources["status"] == "unattached")].assign(reason="unattached disk"),
resources[(resources["type"] == "disk") & resources["attached_to"].isin(stopped_ids)].assign(reason="disk of a stopped server"),
resources[(resources["type"] == "public_ip") & (resources["status"] == "unattached")].assign(reason="unused IP address"),
resources[(resources["type"] == "snapshot") & (resources["created_date"] < TODAY - pd.Timedelta(days=365))].assign(reason="snapshot over a year old"),
])
waste["monthly_usd"] = waste["hourly_usd"] * HOURS_PER_MONTH
summary = waste.groupby("reason").agg(items=("resource_id", "size"), monthly_usd=("monthly_usd", "sum")).round(2)
print(summary)
print("Total: quot;, round(waste["monthly_usd"].sum(), 2), "a month")items monthly_usd
reason
disk of a stopped server 4 35.00
idle server 3 292.00
snapshot over a year old 20 212.50
unattached disk 8 380.01
unused IP address 3 10.95
Total: $ 930.47 a monthThe unattached disks cost the most in total, but the idle servers are the most expensive individual resources. Here they are, with what's known about them:
waste.loc[waste["reason"] == "idle server", ["name", "size", "environment", "team", "created_date", "cpu_max", "monthly_usd"]].round(2)name size environment team created_date cpu_max monthly_usd
62 test-old-migration xlarge development NaN 2025-03-10 0.9 146.0
64 tmp-load-test large NaN NaN 2025-06-02 0.9 73.0
66 poc-reports large development NaN 2025-08-19 0.9 73.0None has a team, and their names suggest one-off projects from 2025. Their CPU never reached 1% in August. They're the clearest candidates for "stop, wait two weeks, delete".
Walkthrough
- Run the cells. How many of the wasteful resources have a team tag?
- Change the snapshot rule to 90 days. How much more would a 90-day retention policy save?
- Work out the annual saving from removing everything in the summary.
- Write the clean-up plan (the task below).
Practice
Practice
What is the total monthly cost of the waste found, in dollars? Two decimal places.
Practice
How many unattached disks are there?
Task
8 minWrite the clean-up plan, one line per kind of waste starting with a dash: at least four lines, each saying how you'll find the owner or check it's unused, the safe removal step, and at least one policy that stops the waste coming back.
Your work is checked for
- At least four lines, each starting with -
- Covers servers, disks and snapshots
- Finds owners (ask, owner, tag, team)
- Safe removal (snapshot first, stop then delete, wait)
- A policy (retention, required tags, automatic)
Check your understanding
Answer every question to check.