Back to case studies
IaC 1 week

Scheduled scaling for non-production environments

Problem

The client came to us with a straightforward observation: their AWS bill for non-production infrastructure was nearly identical to production, despite the fact that no one was actually using those environments between 7 PM and 8 AM, or on weekends. They had three separate environments — development, staging, and a QA environment used for pre-release validation — each running a full complement of Cloud Run services alongside Cloud SQL instances sized to mirror production. The Cloud SQL instances alone were running continuously, burning compute and memory through the night for workloads that generated zero traffic.

What made this particularly wasteful was the stateless nature of most of the workloads. The Cloud Run services themselves scaled to zero when idle, but the underlying Cloud SQL instances were always-on, always-billing. The team had grown accustomed to this as a given — databases need to be up, so they stay up. No one had questioned whether “up” needed to mean “running at full capacity at 3 AM on a Saturday.” Across three environments, the combined monthly cost for non-production infrastructure was sitting at around $4,300, with roughly $2,800 of that attributable to hours when no engineer was logged in.

What we did

We implemented a scheduled scaling solution using Cloud Scheduler to orchestrate stop and start operations against each environment’s Cloud SQL instances, coordinated with Cloud Run’s native scale-to-zero behavior. The approach was deliberately simple: Cloud Scheduler triggers a Cloud Run job twice daily — once at 7 PM local time to stop the database instances, and once at 8 AM to start them and allow time to warm up before the team’s day begins. Weekends follow the same logic, with instances remaining stopped from Friday evening through Monday morning.

All of it was expressed in Terraform, extending the client’s existing infrastructure definitions rather than introducing a parallel management layer. Each environment got its own scheduler pair, with separate service accounts scoped to only the permissions required to stop and start instances in that environment — no broader Cloud SQL Admin role, just the minimum necessary. We also wired in a lightweight Slack slash command backed by a small Cloud Run service that an engineer can call to bring an environment up on demand — useful for the occasional Saturday release or unexpected debugging session. The override keeps the environment running for a configurable window (defaulting to four hours) before the scheduler resumes its normal cadence.

Result

After the first full month, non-production cloud spend dropped from approximately $4,300 to around $1,500 — a 65% reduction, landing almost exactly where our back-of-napkin estimate had predicted. The $2,800 monthly saving came almost entirely from eliminating idle Cloud SQL compute hours, which account for a disproportionate share of database cost when instances are sized for realistic load testing rather than minimal dev traffic.

From the engineering team’s perspective, the change was essentially invisible. Environments are consistently warm and accepting connections by 8:30 AM, giving the scheduler and instance startup a comfortable buffer before standup. In the first two months of operation, the Slack override command was used four times — twice for planned weekend work, twice for on-call investigations — which validated the assumption that the vast majority of non-production usage is predictably within working hours. The client now has a reusable Terraform module they can apply to any future environment they provision, with the scheduled scaling behaviour included by default rather than retrofitted later.

Key highlights

  • 65% reduction in non-production cloud spend
  • Saved ~$2,800/month across 3 environments
  • Environments warm and ready by 8:30 AM local time
  • Override mechanism for off-hours work via Slack command

Tech stack

TerraformCloud SchedulerCloud RunCloud SQL

Have a similar challenge?

Book a call