It started with a Slack message from our ops lead: "Why is our AWS bill up $200 this month?"
After 20 minutes of digging through Cost Explorer, I found it: three staging environments — API, frontend, and workers — all running continuously since the last sprint planning session. Nobody had touched them since the previous Thursday. It was now Tuesday.
I decided to properly calculate what "always-on" staging environments actually cost, using real public cloud pricing. I also wanted to understand how much of that time they're actually being used. The results were worse than I expected.
I pulled public on-demand pricing from AWS, GCP, Fly.io, Heroku, and Render as of September 2026. No reserved instances, no committed-use discounts, no EDP contracts — just the published hourly rate a new user would pay.
For utilization, I used a realistic "active developer workday" model: a staging environment is actually being used when someone is actively deploying to it or running a QA session against it. That works out to roughly:
Active hours per month:
8 hours/day × 5 days/week × ~2.6 weeks = ~105 hours
Total hours in a month: 730 hours
Utilization: 105 / 730 = 14.4%
Idle time: 86%
That 86% number is the uncomfortable one. And it assumes every weekday has active usage — in practice, most staging environments have significant idle stretches even during the week.
Here's the full breakdown by provider and instance type, for a single staging environment:
| Provider | Instance / Config | Hourly rate | Monthly cost (730 hrs) | Active hrs used | Monthly waste |
|---|---|---|---|---|---|
| AWS EC2 | t3.medium (2 vCPU, 4GB) | $0.0416 | $30.37 | ~105 hrs | $26.00 |
| AWS EC2 | t3.large (2 vCPU, 8GB) | $0.0832 | $60.74 | ~105 hrs | $52.00 |
| AWS ECS Fargate | 0.5 vCPU, 1 GB RAM | $0.0189 | $13.79 | ~105 hrs | $11.82 |
| AWS ECS Fargate | 1 vCPU, 2 GB RAM | $0.0379 | $27.67 | ~105 hrs | $23.70 |
| GCP Cloud Run | 0.5 CPU, 256 MB (min-instances=1) | $0.0180 | $13.14 | ~105 hrs | $11.26 |
| GCP Cloud Run | 1 CPU, 512 MB (min-instances=1) | $0.0360 | $26.28 | ~105 hrs | $22.52 |
| Fly.io | shared-cpu-1x, 256 MB | $0.0078 | $5.70 | ~105 hrs | $4.89 |
| Fly.io | shared-cpu-2x, 512 MB | $0.0156 | $11.39 | ~105 hrs | $9.76 |
| Heroku | Standard-1X dyno | $0.0342 | $25.00 | ~105 hrs | $21.43 |
| Heroku | Standard-2X dyno | $0.0685 | $50.00 | ~105 hrs | $42.86 |
| Render | Starter (512 MB, spin-down on free tier) | — | $0 (free tier) | ~105 hrs | $0 |
| Render | Starter paid (always-on) | $0.0096 | $7.00 | ~105 hrs | $6.00 |
| Render | Standard (always-on) | $0.0274 | $20.00 | ~105 hrs | $17.14 |
Pricing sourced from public AWS, GCP, Fly.io, Heroku, and Render pricing pages, September 2026. On-demand / pay-as-you-go rates, no reserved pricing applied. GCP Cloud Run minimum-instances billing used for always-on configuration. Waste calculated at 86% idle (105 active hours / 730 total hours).
One environment is annoying. But most teams don't have one staging environment — they have one per service. A typical microservices team with 3–5 services each needing staging infra:
| Team size / config | Provider | Envs | Cost/env/mo | Total/mo | Annual waste |
|---|---|---|---|---|---|
| Small team, 3 services | AWS ECS Fargate (0.5 vCPU) | 3 | $13.79 | $41.37 | $425/yr |
| Small team, 3 services | AWS EC2 t3.medium | 3 | $30.37 | $91.11 | $940/yr |
| Mid team, 5 services | AWS EC2 t3.medium | 5 | $30.37 | $151.85 | $1,567/yr |
| Mid team, 5 services + DBs | AWS EC2 t3.medium/large mix | 8 | $45.00 avg | $360.00 | $3,715/yr |
| Larger team, 10 services | AWS ECS Fargate (1 vCPU mix) | 10 | $27.67 | $276.70 | $2,855/yr |
I pulled deployment and traffic logs from a few projects to understand what staging environment utilization actually looks like during a typical sprint. The pattern is consistent:
Monday 9am → deploy new branch, run smoke tests (2h)
Monday 11am → developer done, moves to feature work
Monday–Friday → environment sits running, waiting
Thursday 2pm → QA session (3h)
Thursday 5pm → QA done, environment still running
Friday–Sunday → environment runs all weekend, zero traffic
Monday 9am → repeat
The environment isn't completely unused — it's just only needed in bursts. The rest of the time it's running at near-zero utilization, burning the same compute cost it would during active use.
This is the key difference between staging and production. Production environments need to be available because real users hit them at unpredictable times. Staging environments have predictable, human-driven usage patterns. They're needed when developers and QA are at their desks, not at 3am on a Saturday.
There are platform-level sleep features, and they help — but only within their own ecosystem:
| Platform | Sleep / scale-to-zero feature | Cross-platform? | Works for AWS ECS? | Works for GCP Cloud Run? |
|---|---|---|---|---|
| Render (free tier) | ✅ Auto spin-down after 15 min | ❌ Render only | ❌ | ❌ |
| Railway | ✅ Sleeps inactive deploys | ❌ Railway only | ❌ | ❌ |
| Fly.io | ✅ Machines API suspend | ❌ Fly only | ❌ | ❌ |
| AWS ECS | ⚠ Manual: set desired count to 0 | ❌ Manual only | ⚠ Manual | ❌ |
| GCP Cloud Run | ✅ Scale-to-zero (but min-instances=1 disables it) | ❌ GCR only | ❌ | ⚠ Config change needed |
| GitHub Actions scheduled | ⚠ Custom scripts possible | ⚠ DIY, fragile | ⚠ DIY | ⚠ DIY |
The gap is teams running infrastructure on AWS ECS, GCP Cloud Run, or bare EC2 — which is where most serious staging environments live. Platform-specific sleep features help Fly and Railway users, but if you're on AWS or GCP, there's no first-party "hibernate my staging environment on a schedule" button. You're either writing custom Lambda functions and EventBridge rules, or you're leaving it running.
The other issue: waking environments back up needs to be fast and reliable. If stopping an environment means a 10-minute cold start the next morning, most teams will just leave it running to avoid the friction. The "saved cost vs. resumed productivity" tradeoff has to actually work.
These numbers don't include associated costs that also run 24/7: RDS instances for staging databases, ElastiCache clusters, load balancers, data transfer, NAT gateway fees. Add those in and the real waste number for a mid-size team is often 2–3× the compute figure alone.
Plug in your actual environment configuration (provider, instance type, number of environments, team working hours) and get a real number for your monthly idle spend.
The calculator also shows the break-even point: how fast environments need to wake up for auto-hibernation to make sense for your team's workflow.
→ Calculate your staging wasteThe core finding is simple: staging environments follow human work schedules, but cloud billing doesn't. A compute instance costs the same whether a developer is actively deploying to it or it's sitting idle at 2am on a Sunday.
For teams on AWS ECS or GCP Cloud Run, there's no easy built-in answer. The options are: pay the full 730-hour rate, maintain custom automation to stop/start environments on a schedule, or accept that this is a known inefficiency and move on.
I think the "known inefficiency" category is where most teams land — not because they've decided it's the right call, but because the solution they'd need to build feels like yak-shaving when there's product work to do.
The first step is knowing your actual number. Once you can see "$78/month in pure idle compute," the tradeoff calculus changes.
Pricing data sourced from public AWS, GCP, Fly.io, Heroku, and Render pricing pages as of September 2026. On-demand rates; no reserved or committed-use pricing applied. Utilization model assumes 8-hour active workdays, 5 days/week, ~2.6 weeks active per month (105 hours). Actual utilization varies by team.