Introduction
Cloud cost inefficiency rarely comes from a single dramatic error —
it accumulates from small, individually reasonable-looking decisions:
an oversized VM chosen "to be safe," a static IP reserved for a test
that was never cleaned up, a storage bucket without a lifecycle
policy. This post deliberately introduces four common sources of cloud
waste, lets them run long enough to appear in billing data, and walks
through identifying and remediating each using Billing Reports and
Recommender.
Solution overview
┌─────────────────────────────────────────────┐
│ Sources of waste │
├─────────────────────────────────────────────┤
│ 1. Oversized Compute Engine instance │
│ 2. Cloud Storage without lifecycle policy │
│ 3. Reserved static IP with no attached resource │
│ 4. Autoscaling ceiling set without usage data │
└─────────────────────────────────────────────┘
│
▼
┌───────────────────────┐
│ Billing Reports + │
│ Recommender API │
└───────────────────────┘
Prerequisites
- A Budget Alert configured on the billing account (recommended threshold: $25) before beginning
- At least 3–4 days of elapsed time between provisioning and analysis, since billing trend data needs a meaningful window to be useful
Walkthrough
Step 1: Provision the waste sources
Oversized instance for a lightweight workload:
gcloud compute instances create oversized-vm \
--zone=asia-southeast1-a --machine-type=n2-standard-8 \
--image-family=debian-12 --image-project=debian-cloud
Storage without a lifecycle policy:
gcloud storage buckets create gs://<PROJECT_ID>-waste-bucket \
--location=asia-southeast1
Idle static IP:
gcloud compute addresses create unused-static-ip --region=asia-southeast1
Autoscaling ceiling set without usage justification:
gcloud compute instance-groups managed set-autoscaling waste-mig \
--zone=asia-southeast1-a --max-num-replicas=20 --min-num-replicas=2 \
--target-cpu-utilization=0.8
Allow this configuration to run for 3–4 days before proceeding to
analysis.
Step 2: Review Billing Reports
In Billing → Reports, filter by the time range covering the
provisioning period and group by Service, then by SKU for finer
granularity. Rank the four sources by actual cost — results frequently
diverge from intuition; for example, an idle static IP typically costs
far less than an oversized VM, but this should be confirmed against
your own data rather than assumed.
Step 3: Query Recommender for automated findings
gcloud recommender recommendations list \
--project=<PROJECT_ID> --location=asia-southeast1-a \
--recommender=google.compute.instance.MachineTypeRecommender
gcloud recommender recommendations list \
--project=<PROJECT_ID> --location=global \
--recommender=google.compute.address.IdleResourceRecommender
Coverage gap to note: Recommender does not currently surface
missing storage lifecycle policies as a recommendation — this class of
waste requires manual review of bucket configuration and billing
trends, reinforcing that automated tooling should supplement, not
replace, periodic manual cost review.
Step 4: Remediate
gcloud compute instances stop oversized-vm --zone=asia-southeast1-a
gcloud compute instances set-machine-type oversized-vm \
--zone=asia-southeast1-a --machine-type=e2-small
gcloud compute instances start oversized-vm --zone=asia-southeast1-a
cat > lifecycle.json <<'EOF'
{
"rule": [
{"action": {"type": "SetStorageClass", "storageClass": "COLDLINE"},
"condition": {"age": 30}},
{"action": {"type": "Delete"}, "condition": {"age": 365}}
]
}
EOF
gcloud storage buckets update gs://<PROJECT_ID>-waste-bucket \
--lifecycle-file=lifecycle.json
gcloud compute addresses delete unused-static-ip --region=asia-southeast1 --quiet
gcloud compute instance-groups managed set-autoscaling waste-mig \
--zone=asia-southeast1-a --max-num-replicas=4 --min-num-replicas=1 \
--target-cpu-utilization=0.7
The revised autoscaling ceiling of 4 should be justified by observed
peak usage during the test window, not set arbitrarily — an
unjustifiably high ceiling creates cost exposure risk even without
generating cost directly, since a traffic spike or application bug
could scale the fleet far beyond actual need.
Measuring savings
Allow 1–2 additional days after remediation, then compare Billing
Reports for the same resource categories before and after the change:
| Category | Cost before (monthly, extrapolated) | Cost after | % reduction |
|---|---|---|---|
| Compute (VM resize) | |||
| Storage (lifecycle policy) | |||
| Idle static IP + LB | |||
| Autoscaling ceiling |
Clean up resources
gcloud compute instances delete oversized-vm --zone=asia-southeast1-a --quiet
gcloud storage rm -r gs://<PROJECT_ID>-waste-bucket
Conclusion
Automated recommenders are a useful first pass, but this exercise
shows they have blind spots — notably storage lifecycle policies — that
still require deliberate, periodic manual review. Building this review
into a regular cadence, rather than a one-time cleanup, is the
practical difference between temporary savings and sustained cost
efficiency.
In Part 8, we close the series by reversing roles: designing a
broken system for someone else — or a future version of yourself — to
diagnose.
Top comments (0)