Cloud

Tuning Cloud Run and Cloud SQL costs for a client on a tight budget

CLD

Cloud bills have a way of drifting upward gradually until someone finally asks why. A client's Cloud Run and Cloud SQL costs had crept up over the past year without any corresponding growth in traffic, so we ran a focused audit rather than assuming the increase was simply the cost of doing business at scale.

Right-sizing an oversized Cloud SQL instance was the single biggest win. The instance had been provisioned for a traffic spike during a launch a year earlier and never scaled back down afterward, which is a common pattern once a team is busy shipping features and nobody owns the recurring job of revisiting infrastructure sizing. Downsizing it, backed by a few weeks of monitoring to confirm the smaller instance handled peak load comfortably, cut that line item by roughly a third on its own.

Setting Cloud Run's minimum instances to zero for a low-traffic staging environment was the second big lever. Staging doesn't need to be always-warm the way production does, and the cold-start latency for the occasional QA session or demo was a completely acceptable tradeoff against paying for an idle instance around the clock. We left production's minimum instances above zero, since cold starts there would have been a real user-facing regression, which is the kind of distinction that's easy to miss when cost-cutting advice gets applied uniformly across environments instead of by their actual traffic patterns.

We built a small internal dashboard pulling from the client's billing export specifically so cost trends would be visible on an ongoing basis rather than something that only gets examined when an invoice finally prompts a question. Before this, cost visibility lived entirely in a monthly PDF invoice that nobody had a specific reason to scrutinize line by line unless the total looked unusually high, which is exactly the kind of gradual drift that's nearly invisible month to month but obvious in hindsight across a full year.

Right-sizing the Cloud SQL instance required more care than just picking a smaller tier and hoping for the best. We pulled several weeks of CPU, memory, and connection-count metrics from Cloud Monitoring first, specifically looking at peak values rather than averages, since an instance that looks comfortably underused on average can still be genuinely undersized for its actual peak load during a busy reporting period at month's end. The downsized instance we landed on was validated against that peak window specifically before we committed to it in production.

Not every cost lever was worth pulling. We considered moving the database off Cloud SQL entirely to a self-managed instance for additional savings, but the operational overhead of managing backups, patching, and failover ourselves outweighed the marginal cost difference for a client without dedicated infrastructure staff on their side. Managed services cost more per unit of compute, but for a client this size, the tradeoff against needing to hire or contract for database operations expertise was straightforward once we actually laid out both sides of it.

A few smaller changes rounded out the audit: moving infrequently accessed backups to a cheaper storage class, and catching a forgotten Cloud SQL read replica that had been spun up for a load test months earlier and never torn down. Combined, the changes cut the monthly bill by nearly 40%, with no user-facing change at all. The bigger lesson for us was procedural rather than technical: we now schedule a quarterly cost review for every client on managed cloud infrastructure, specifically so instance sizing and forgotten resources don't get to compound silently for another year before anyone notices.

← Back to the journal

Have a project in mind?
Let’s talk.

Tell us where you are and where you want to go. We'll map the fastest route between the two.

Currently accepting new clients