GCP / Guide 10
Cost hygiene
Billing reports and export, budgets, the monthly clean-up checklist, committed use discounts and Spot VMs.
Google Cloud bills rarely grow because of one big mistake. They grow from many small ones: a VM nobody stopped, disks left behind, reserved IP addresses, logs kept forever, data crossing regions. Cost hygiene is a monthly routine that finds them, plus paying less for what you keep.
See where the money goes
- Billing reports (Billing > Reports): group by Project, then Service and SKU, then by your
costcenterandapplicationlabels. Compare the last three months; changes matter more than totals. - SKU explains surprises: network egress between regions and to the internet, Cloud NAT data processing, external IP addresses and log ingestion often appear near the top and are easy to miss.
- Billing export to BigQuery (standard and detailed usage cost, plus pricing) for line-item analysis and showback reports. Turn it on from day one: it isn't retroactive (Guide 3).
- FinOps hub in the console brings together savings recommendations, commitment utilisation and waste across the billing account.
-- Last month's net cost by project and service (BigQuery billing export)
SELECT
project.id AS project,
service.description AS service,
ROUND(SUM(cost) + SUM(IFNULL((SELECT SUM(c.amount) FROM UNNEST(credits) c), 0)), 2) AS net_cost
FROM `prj-billing-export.billing.gcp_billing_export_v1_012345_6789AB_CDEF01`
WHERE invoice.month = FORMAT_DATE('%Y%m', DATE_SUB(CURRENT_DATE(), INTERVAL 1 MONTH))
GROUP BY project, service
ORDER BY net_cost DESC
LIMIT 25
Set budgets and alerts
- A budget per project (or per folder or label), with alerts at 50%, 90% and 100% of actual spend and at 100% of forecast. Forecast alerts give you time to act before the month ends.
- Budgets don't stop spending. They only notify. For sandbox projects, send budget notifications to Pub/Sub and have a Cloud Run function stop VMs or disable billing on the project when the budget is exceeded, knowing that disabling billing shuts services down.
- Anomaly detection in Billing flags unusual spend spikes by project and service. Check that the right people get the emails.
# Budget of $500 a month on one project, with alerts at 50%, 90%, 100% and forecast 100%
gcloud billing budgets create --billing-account=012345-6789AB-CDEF01 --display-name="prj-notes-test monthly" `
--budget-amount=500USD --filter-projects=projects/prj-notes-test `
--threshold-rule=percent=0.5 --threshold-rule=percent=0.9 --threshold-rule=percent=1.0 `
--threshold-rule=percent=1.0,basis=forecasted-spend
The monthly clean-up checklist
Find-GcpOrphanedResources.ps1 covers most of this list across every project:
| Look for | Why it costs |
|---|---|
| Unattached persistent disks | Charged per GB-month whether attached or not |
| Old snapshots and custom images nobody uses | Charged per GB stored |
| Reserved external IP addresses not in use | Unused static IPs are charged at a higher rate than ones in use |
| VMs stopped for weeks | No compute charge, but disks and reserved IPs still bill; snapshot and delete |
| Load balancer backend services with no backends | Forwarding rules are charged hourly, doing nothing |
| Idle Cloud SQL instances | Stop non-production instances out of hours (storage still bills) |
| Log buckets with long retention, and verbose logs | Ingestion and storage (Guide 9) |
| Forgotten projects | Old proofs of concept with running resources; the unattended project recommender finds them |
Recommender (Active Assist) does much of the finding for you: idle VMs, idle persistent disks, idle IP addresses, idle Cloud SQL instances, machine type rightsizing and unattended projects, each with an estimated saving. Review them in the FinOps hub or the Recommendation Hub monthly.
# Idle disk recommendations for one zone
gcloud recommender recommendations list --project=prj-notes-test --location=us-east1-b `
--recommender=google.compute.disk.IdleResourceRecommender `
--format="table(description, primaryImpact.costProjection.cost.units)"
Pay less for what you keep
| Option | How it works | Use for |
|---|---|---|
| Sustained use discounts | Automatic, for eligible machine series running much of the month | Nothing to do; know which series get them |
| Resource-based committed use discounts | Commit to vCPUs, memory, GPUs or local SSD in a region for 1 or 3 years | Steady, predictable VM fleets that won't change region |
| Compute flexible CUDs (spend-based) | Commit to an hourly spend for 1 or 3 years across Compute Engine, GKE and Cloud Run, any region and machine family | Steady spend that moves between services and regions |
| Spend-based CUDs for other services | Commit to spend on Cloud SQL, Memorystore, Cloud Run and others | Databases and managed services you'll keep |
| Spot VMs | Much cheaper, but can be stopped at any time | Batch, CI, stateless and fault-tolerant work |
- Rightsize first, then commit. A commitment on an oversized fleet locks in the waste.
- Commit to the floor, not the average: cover the usage that's there at 3 a.m. on a Sunday, and let on-demand and Spot handle the rest. The CUD recommendations in the console do the maths.
- Share commitments across the billing account (CUD sharing), so a discount bought in one project covers matching use in others, and track utilisation monthly.
- Google changed how spend-based CUDs appear on the bill (discounts applied to the price instead of credits). If you have reports built on the billing export, check them against Google's data model notes for the change.
Storage and network
- Cloud Storage Autoclass moves objects between Standard, Nearline, Coldline and Archive by access pattern; lifecycle rules do it on a schedule for data you know is cold, and delete old versions.
- Egress is charged when data leaves a zone, region or Google's network. Keep chatty services in one region, use Private Google Access and Cloud CDN, and watch cross-region replication you didn't mean to set up.
- Cloud NAT charges per gigabyte processed; traffic to Google APIs should use Private Google Access instead of going through NAT.
- Persistent disk type: balanced rather than SSD where latency allows; don't over-provision Hyperdisk IOPS.
Make it routine
- A monthly cost review with the owners of the top ten cost items: what changed, what can go, what to commit to.
- Stop schedules for non-production (
Invoke-GcpVMPowerSchedule.ps1, or native instance schedules) and budgets on every sandbox project. - Label compliance as a standing item: unlabelled cost is cost nobody owns (
Get-GcpUnlabeledResources.ps1). - Show the savings. A monthly note on what was removed and what it saved keeps the routine funded.