# I Was Paying for Servers Nobody Used. So I Moved to Cloudflare.

Canonical: https://www.dharmikjagodana.com/blogs/cloud-run-vs-cloudflare-workers-cost
Published: 2026-11-02
Description: Cloud Run vs Cloudflare Workers for a small SaaS: a warm instance, a BullMQ worker and Redis add up to about $48 a month idle. Workers Paid starts at $5.

I posted on X that I'm going all in on Cloudflare for my new product, [MakerRadar](https://makerradar.io/).

DB, queues, compute, security, domains. Everything.

MakerRadar is a weekly launch board for apps, shops, services and makers, where every listing gets a permanent, search-friendly page so it can be found on Google and in AI answers. I'm building it now.

The reason I picked Cloudflare is boring. **Money.** Specifically, the money I used to pay while nobody was using my products. So this is Cloud Run vs Cloudflare Workers from the angle that actually hurt: the idle bill.

_No real Cloudflare bill yet. The numbers below are list-price estimates, not my invoices._

* * *

## What I was paying for on GCP

My previous products ran on Google Cloud. Cloud Run for the services. BullMQ on Redis for background jobs. A worker process to pull those jobs.

Cloud Run itself wasn't the problem. By default, it scales to zero when nobody is using it.

But scale to zero means cold starts. So I set a minimum instance to keep one warm. That instance is billed all the time, busy or not.

Then the pieces around it. BullMQ needs Redis running all the time, and a worker process listening to it. Neither of those scales to zero either.

So on a quiet day, nothing was happening and I was still paying for three things.

> Idle isn't free. It's just quiet.

My Redis alone was **$7 a month**. Small, but I paid it every month, busy or not.

* * *

## Cloud Run vs Cloudflare Workers: the idle month

Here's what that old shape costs at today's list prices, next to the same small SaaS on Cloudflare.

**The Cloud Run lines are estimates from public list prices on 22 October 2026, not my bill.** The Redis line is my real cost from my old setup. Google prices are for us-central1 (Iowa), on-demand, with no committed-use discounts. A month is 730 hours, or 2,628,000 seconds.

The small SaaS I'm pricing:

- One web/API service with 1 vCPU and 512 MiB, kept warm with one minimum instance.
- One background worker with 1 vCPU and 512 MiB, running all the time for BullMQ.
- Redis for BullMQ, at what I actually paid: $7 a month.
- Traffic: 300,000 requests a month, about 5 ms of CPU each, and 50,000 background jobs.

### The GCP side

From the [Cloud Run pricing page](https://cloud.google.com/run/pricing), plus my real Redis cost:

- **Warm Cloud Run instance.** With request-based billing, a minimum instance is billed at the idle rate when it isn't serving: $0.0000025 per vCPU-second and $0.0000025 per GiB-second.
  CPU: 2,628,000 × $0.0000025 = $6.57. Memory: 0.5 GiB × 2,628,000 × $0.0000025 = $3.29. **About $9.86.**
- **Always-on worker.** A BullMQ worker has to run all the time, so I priced it as a Cloud Run worker pool: $0.000011244 per vCPU-second and $0.000001235 per GiB-second.
  CPU: 2,628,000 × $0.000011244 = $29.55. Memory: 0.5 × 2,628,000 × $0.000001235 = $1.62. **About $31.17.**
- **Redis.** My actual cost: **$7 a month.**

Cloud Run cost scales with instance size, because both rates are per vCPU and per GiB. The numbers above assume 1 vCPU and 512 MiB. At 2 vCPU and 1 GiB, the same math doubles: about $19.71 for the warm instance and $62.34 for the worker pool, or about $89 a month with Redis.

Active request time on top of the idle rate is small at this traffic, so I left it out.

### The Cloudflare side

From the [Workers pricing page](https://developers.cloudflare.com/workers/platform/pricing/). The Workers Paid plan is **$5 a month** per account, and it includes:

- 10 million requests and 30 million CPU milliseconds
- 1 million Queues operations
- 25 billion D1 rows read, 50 million rows written, 5 GB of storage
- 10 million KV reads

The same small SaaS uses:

- Requests: 300,000. Included.
- CPU: 300,000 × 5 ms = 1.5 million CPU ms. Included.
- Queues: a message takes about 3 operations (write, read, delete). 50,000 × 3 = 150,000. Included.
- D1 and KV at this size: included.

Total: **$5.00.** There are no egress or bandwidth charges.

### Side by side

| Monthly | GCP (estimate + real Redis) | Cloudflare (list price) |
| --- | --- | --- |
| Web/API compute | $9.86 (warm Cloud Run instance) | Included in $5 (Workers) |
| Background worker | $31.17 (Cloud Run worker pool) | Included in $5 (Queues, Cron Triggers) |
| Queue backend | $7.00 (my real Redis cost) | Included in $5 (Queues) |
| **Total** | **about $48.03** | **$5.00** |

That's about **$43 a month**, or around $516 a year, for a product that's mostly quiet. With 2 vCPU and 1 GiB instances, the gap grows to about $84 a month.

What's not in that table, to be fair:

- **Free tiers.** Cloud Run has a monthly free tier per billing account. For the worker pool alone, it takes the line down to about $25.95. I left free tiers out on both sides.
- **The database.** The GCP side has no database at all. On Cloudflare, D1 is inside the $5 at this size.
- **Networking and logs.** Not counted on either side.
- **The honest counterpoint.** A Cloud Run service with no minimum instance and no Redis would likely sit inside Cloud Run's free tier at this traffic, which beats $5. My problem wasn't Cloud Run's per-request price. It was everything I kept running so the product felt fast.

> If nobody uses the product, I shouldn't be paying for it to wait.

* * *

## Why there's no warm instance to pay for

I kept an instance warm on Cloud Run because of cold starts. Workers don't have the same problem.

Workers run in [V8 isolates](https://developers.cloudflare.com/workers/reference/how-workers-works/), not a container per service. Cloudflare's docs say an isolate is created inside an already running environment, which "eliminates the cold starts of the virtual machine model." They also say an isolate can start around a hundred times faster than a Node process on a container or VM.

So there's no minimum instance setting to pay for. Billing follows requests and CPU time. Time spent waiting on a database or an API isn't CPU time.

Background work maps over the same way:

- **Cloud Run services** become **Workers**.
- **BullMQ and Redis** become **Queues** for background jobs, **Workflows** for multi-step jobs, and **Cron Triggers** for scheduled ones.

None of those need a process sitting there waiting.

* * *

## Security you get without setting anything up

Fewer moving parts also means fewer things to secure. Here's what Cloudflare's docs say you get by default.

- **DDoS protection.** Cloudflare detects and mitigates DDoS attacks automatically, and [standard DDoS protection is unmetered on all plans](https://developers.cloudflare.com/ddos-protection/), layers 3 to 7.
- **Free TLS certificates.** By default, Cloudflare issues and renews [free Universal SSL certificates](https://developers.cloudflare.com/ssl/edge-certificates/universal-ssl/) for domains added and activated on Cloudflare.
- **Certificates for Workers too.** When you attach a Worker to a custom domain, Cloudflare creates the DNS record and issues the certificate for you.
- **Isolation.** Each isolate's memory is isolated, so one piece of code is protected from other code on the same runtime.
- **Less to look after.** No Redis and no always-on worker means fewer things that need updates.

Then there are extras that are available, but you have to turn them on:

- **Turnstile**, a CAPTCHA alternative, on the free plan.
- **The Free Managed Ruleset** in the WAF, available on all plans.
- **Rate limiting rules** and the Workers rate limiting binding.
- **Cloudflare Access** to put a login in front of internal tools.

Default is a floor, not a finish line. But it's a floor you get without running anything extra.

* * *

## Deploy guardrails when an agent ships the code

I use Claude Code day to day for features, deployment setup and security checks. Claude cloud agents and my Grok Bot assistants help with the same work. Fewer moving parts doesn't mean an agent should get the keys.

I wrote about the commands I never let an agent run in [The Commands I Never Let an AI Agent Run](/blogs/ai-agent-commands-never-run-openclaw-sandbox). On Cloudflare, it comes down to two rules.

**The token decides what's possible.** Deploy with a scoped Cloudflare API token stored in your CI provider's secrets, not in the repo. Start from the "Edit Cloudflare Workers" template and add only what the deploy needs.

**The agent asks before production.** In Claude Code, put [permission rules](https://code.claude.com/docs/en/permissions) in a committed `.claude/settings.json`. Rules are checked deny, then ask, then allow:

```json
{
  "permissions": {
    "ask": [
      "Bash(npx wrangler deploy *)",
      "Bash(npx wrangler rollback *)",
      "Bash(npx wrangler d1 migrations apply *)"
    ],
    "deny": [
      "Bash(npx wrangler delete *)",
      "Bash(npx wrangler d1 delete *)",
      "Read(./.dev.vars)"
    ]
  }
}
```

Write each rule the way the command is actually typed. A rule for `wrangler deploy *` doesn't match `npx wrangler deploy`. And these rules match command text, so they aren't a security boundary on their own. That's why the token comes first.

* * *

## Final thought

Going all in on one provider is a bet. If Cloudflare has a bad day, so do I.

But I've paid for warm instances and idle Redis for long enough. For a new product, a $5 floor that only grows when people actually use it is the trade I want.

Once MakerRadar has a full month on Cloudflare, I'll share the real bill.

I write about building real products with AI agents: setups, costs, and what breaks. One email when there is a new post.

[Subscribe](https://dharmikjagodana.beehiiv.com/subscribe).

Moved off Cloud Run, Lambda or a VPS to save money? Tell me what it cost you on [X](https://x.com/dharmikjagodana).
