
Scale to zero sounds like an obvious win: no traffic, no bill. For a small SaaS app the honest question is at what traffic it stops being the cheap option, and which model takes over. We worked it out from the current price pages for the same app at 10 thousand, 100 thousand, 1 million and 10 million requests a month.
Short version: below about 1 million requests, per-request billing costs next to nothing, and free tiers cover most of it. Without free tiers, Lambda costs $1.03 per million requests for this app, so it reaches a $7 server at about 6.8 million. Cloud Run with 1 vCPU costs $2.92 per million and crosses at about 2.4 million. A cold start adds almost nothing to the bill; its cost is the wait.
The app and the rates
The app answers each request in 100 ms and needs 512 MB, which is typical for the small apps in our idle memory test. All prices are us-east-1 or Iowa, for a 30-day month. We count compute and request charges only. Data transfer, a database and logs come on top of every option; a database doesn't scale to zero just because the app does.
| Model | Example | Rate | Free each month |
|---|---|---|---|
| Per request and GB-second | [AWS Lambda](https://aws.amazon.com/lambda/pricing/), x86 | $0.20 per million requests, $0.0000166667 per GB-second | 1 million requests, 400,000 GB-seconds |
| Per vCPU-second, while handling requests | [Cloud Run](https://cloud.google.com/run/pricing), request-based | $0.000024 per vCPU-second, $0.0000025 per GiB-second, $0.40 per million requests | 180,000 vCPU-seconds, 360,000 GiB-seconds, 2 million requests |
| Per vCPU-second, all the time | Cloud Run, instance-based | $0.000018 per vCPU-second, $0.000002 per GiB-second | 240,000 vCPU-seconds, 450,000 GiB-seconds |
| Always-on container | [Fargate](https://aws.amazon.com/fargate/pricing/) + [load balancer](https://aws.amazon.com/elasticloadbalancing/pricing/) | $0.04048 per vCPU-hour, $0.004446 per GB-hour, $0.0225 per load balancer hour, $0.008 per LCU-hour, $0.005 per public IP hour | None counted |
| Always-on server | [Lightsail](https://aws.amazon.com/lightsail/pricing/) 1 GB, 2 vCPU | $7 a month, 2 TB transfer included | None counted |
Monthly cost by traffic
With each vendor's free tier applied, for a single app on an otherwise empty account:
| Requests a month | Lambda | Cloud Run, request-based | Cloud Run, instance-based | Fargate + load balancer | Lightsail $7 |
|---|---|---|---|---|---|
| 10,000 | $0.00 | $0.00 | $44.03 | $36.46 | $7.00 |
| 100,000 | $0.00 | $0.00 | $44.03 | $36.46 | $7.00 |
| 1,000,000 | $0.00 | $0.00 | $44.03 | $36.46 | $7.00 |
| 10,000,000 | $3.47 | $23.23 | $44.03 | $38.77 | $7.00 |
Free tiers are per account, so your second app, or a busier first one, doesn't get them. The same table without free tiers shows the real slope. Lambda's second column adds API Gateway HTTP API at $1 per million requests, if you use it rather than a free function URL:
| Requests a month | Lambda | Lambda + HTTP API | Cloud Run, request-based | Cloud Run, instance-based | Fargate + load balancer | Lightsail $7 |
|---|---|---|---|---|---|---|
| 10,000 | $0.01 | $0.02 | $0.03 | $49.25 | $36.46 | $7.00 |
| 100,000 | $0.10 | $0.20 | $0.29 | $49.25 | $36.46 | $7.00 |
| 1,000,000 | $1.03 | $2.03 | $2.92 | $49.25 | $36.46 | $7.00 |
| 10,000,000 | $10.33 | $20.33 | $29.25 | $49.25 | $38.77 | $7.00 |
The worked line at 1 million requests. Lambda: 1,000,000 x 0.1 s x 0.5 GB = 50,000 GB-seconds x $0.0000166667 = $0.83, plus $0.20 for requests = $1.03. Cloud Run, request-based: 100,000 vCPU-seconds x $0.000024 = $2.40, 50,000 GiB-seconds x $0.0000025 = $0.125, plus $0.40 for requests = $2.92. Fargate: 720 h x (0.25 x $0.04048 + 0.5 x $0.004446) = $8.89, and the load balancer with its addresses and the task's public IP brings it to $36.46.
Two assumptions lean against Cloud Run. It handles up to 80 requests at once per instance by default and bills instance time, so overlapping requests share the charge; we assumed no overlap, which is close at low traffic and an upper bound at 10 million. And a vCPU of 1 is more than Lambda's share at 512 MB, so the two aren't equal in CPU; a CPU-heavy request would finish faster on Cloud Run.
Where the lines cross
| Per-request option | Cost per million (no free tier) | Reaches a $7 server | Reaches Fargate + load balancer ($36.46) | Reaches instance-based Cloud Run ($49.25) |
|---|---|---|---|---|
| Lambda | $1.03 | 6.8 million | 35 million | 48 million |
| Lambda + HTTP API | $2.03 | 3.4 million | 18 million | 24 million |
| Cloud Run, request-based | $2.92 | 2.4 million | 12 million | 17 million |
For scale, 10 million requests a month is about 3.9 a second on average: at 100 ms each, that is well within one small always-on server's reach, if it is steady. Those crossings move fast with the app. At 300 ms and 1 GB, Lambda costs $5.20 per million and Cloud Run $8.35, so the $7 server is reached at about 1.3 and 0.8 million. So slow code moves you to always-on sooner, and speeding up a handler lowers a per-request bill directly while doing nothing for a fixed one.
Also compare what you are buying. The server has one failure domain and you patch it. The load balancer setup spans zones. The per-request options add capacity by themselves when a spike arrives, and a fixed one returns errors or queues. A spike is exactly when you would not want to be doing arithmetic.
What cold starts add
Scale to zero means the first request after a quiet spell starts the app. On the bill this is tiny. Lambda bills initialisation as duration, and even in the worst case, with every request cold, 10,000 cold starts of a small app are cents. We took start-up times from our cold start measurements, container start to first response on our test machine, as a stand-in:
| Runtime | Start-up | Billed per 1,000 cold starts at 512 MB | 10,000 requests a month, all cold |
|---|---|---|---|
| PHP or plain Java | 0.35 s | $0.0029 | $0.03 |
| .NET or FastAPI | 0.65 s | $0.0054 | $0.05 |
| Spring Boot | 2.10 s | $0.0175 | $0.18 |
The price of a cold start is the wait. At 10,000 requests a month, one every 4.3 minutes on average, a large share of your visitors could hit one, and a Spring Boot user waits over 2 s, on top of the request. Keeping one instance warm is what ends this, and it is also where scale to zero stops being zero: on Cloud Run, a minimum instance at 1 vCPU and 512 MiB is billed while idle at $0.0000025 per vCPU-second and per GiB-second:
So keeping it warm costs about what the always-on server does. If your users can't tolerate a cold start, the cheap end of the table isn't really available to you.
Which to pick
| Your app | Pick | Why |
|---|---|---|
| Under about 1 million requests, quiet for hours, start-up under 1 s | Per-request | Close to free, and a cold start is tolerable |
| Same traffic, a slow start or users who notice | Always-on small server | About $7 flat, no wait |
| Steady 5 million or more requests, or slow handlers | Always-on | Past the crossing, and it stays flat as you grow |
| Spiky: quiet, then 100x for an hour | Per-request or request-based container | You pay for the spike and nothing else |
| Many small apps, each mostly idle | Containers that sleep and wake | Each costs little while idle; memory and start-up decide how many fit |
If you run on AWS's push-a-container service, see also what closing App Runner to new customers does to these numbers, and if your sessions run someone else's code, the sums are different: see Lambda MicroVMs.
Sources (read 3 Nov 2026): AWS Lambda pricing; Cloud Run pricing, Tier 1, us-central1; Fargate pricing; Elastic Load Balancing pricing; VPC pricing for public IPv4; Lightsail pricing; API Gateway pricing. Totals and crossings are our own arithmetic; LCU use (0.1 on average, 0.5 at 10 million) is our assumption.
On systemi an app runs in a container that sleeps when idle and wakes on the next request, deployed from a zip or an https git URL and a branch.
See how deploys work

