Cloud
Your AWS invoice is a design review you already paid for
ZenHorizon Engineering · 4 December 2024 · 5 min
December is when finance forwards a PDF and asks why compute doubled. Engineering opens Cost Explorer, stares at a bar chart, and says “we will look at it in January”. Nobody looks at it in January. The line item becomes weather.
We stopped treating the invoice as an accounting artefact. It is a design review with a delay. The architecture already happened. The bill is just late to the meeting.
This is not a lecture about being cheap. Some products should spend. A payments API that needs multi-AZ RDS is not the villain. The villain is spend nobody can narrate. If you cannot say why a line exists, you cannot say whether to keep it.
The three line items we see every winter
1. Environments that were copied, not designed
Someone cloned prod to make staging. Then cloned staging to make “qa-2” for a partner demo. NAT gateways multiply — they are still one of the quietest $30-plus-a-month habits in a VPC. RDS instances sit at prod size because “we might load test”. Load testing never happens. The instances stay.
A staging environment needs production-shaped data and production-shaped failure modes. It does not need production-shaped spend. Smaller instances, scaled-to-zero where the runtime allows, and a weekly job that deletes anything older than 14 days with a `tmp-` prefix. If you cannot delete it, it was never temporary.
We once found four load balancers for a service that had one listener. Two were from a blue/green experiment that ended in March. Nobody owned the Terraform because it had been applied from a laptop. The invoice remembered. The repo did not.
2. Data paths with no ceiling
The quiet killer is egress and chatty services. A microservice that loads a full user object to render a badge. A nightly export that pulls the same 80GB into a warehouse that already has it. CloudFront in front of a bucket that should have been a signed URL with a cache policy someone actually wrote down.
CloudWatch Logs ingestion is the other sleeper. Debug logging left on in production, or a Lambda that prints the entire event, will outspend the function. We have seen log bills larger than compute. Nobody designs that. They just never turn the level back to info.
We ask one question in design review: what is the unit cost of the happy path at 10x traffic? If nobody can answer, the feature is not ready to be “elastic”. Elastic is a word people use when they have not done the arithmetic.
3. Temporary that became load-bearing
Lambda that was a weekend prototype. A NAT instance “until we fix the VPC”. A third-party log drain that charges per GB and is now the only place anyone can debug. These are not surprises. They are decisions without an expiry date.
Put a `review-by` tag on anything you would be embarrassed to explain to finance. Calendar it. If the date passes and the thing is still there, it is architecture. Budget it like architecture.
What we do before buying a FinOps platform
Platforms are fine once you have a habit. Buying one to create the habit is how you get another dashboard nobody opens. Do this first.
- One cost allocation tag that is mandatory in Terraform or CDK — usually `service` plus `env`. No tag, no merge. Harsh. Effective.
- A weekly 20-minute review: top five rising services, one owner each, one action or an explicit “accept”.
- Budgets with a human on the other end of the email, not a Slack channel named #alerts that everyone muted in 2023.
- Reserved capacity or Savings Plans only after the shape of compute has been stable for a month. Buying commitment on a prototype is how you fund the wrong shape.
- S3 lifecycle rules on any bucket that is not a source of truth. Most “backups” are unexamined copies.
The weekly review is the whole trick. Twenty minutes, same time, same three people: whoever owns infra, whoever owns the noisiest product, and someone who can say yes to deleting an environment. If the meeting needs a slide, it is already too rare.
Graviton, spot, and other keynote habits
re:Invent will keep announcing cheaper chips and clever storage classes. Moving a stateless fleet to Graviton is often real money. So is turning on origin shield. So is not running Kubernetes etcd on the instance family that was nearest in the console.
Do those after the forgotten environments are gone. We have watched teams spend a quarter on an ARM migration while `qa-2` sat at prod size in ap-south-1. The migration was interesting. The idle database was the invoice.
A tagging scheme that survives a new hire
We use three tags and we are boring about them: `service`, `env`, `owner`. Owner is an email or a team name that still exists when the original author leaves. Everything else — `project`, `cost-center`, `customer` — is optional until finance asks. Optional tags that nobody fills are worse than few tags that CI enforces.
If you are on Terraform, the default tags go on the provider. If someone opens the console and clicks, the weekly review will show an untagged line. That line gets a name or a delete. There is no third option called “we will tag it later”.
We keep a one-page glossary for finance: what `service=api` means, what `env=staging` is allowed to cost, who to ping. The glossary prevents the meeting from becoming a translation exercise. Translation exercises are how weekly reviews die.
Read the invoice like a PR comment. It is already telling you what the design did not.