Run the numbers on a realistic multi-tenant SaaS — 500 tenants, each generating 100,000 requests a month — and Cloudflare's Workers for Platforms bills $42.80. That's $0.086 per tenant. Price the same 500 tenants as always-on Kubernetes namespaces on owned Hetzner boxes, sized the same way this site's earlier Render-vs-Hetzner math sized always-on containers, and the bill is $85 — $0.17 per tenant, roughly double. At this workload, on this architecture, Cloudflare's metered platform-for-platforms fee wins outright.
That result cuts against the reflexive "self-hosting is always cheaper" instinct, and it's worth sitting with rather than explaining away, because the mechanism behind it is the actual answer to what a layered SaaS-on-Workers billing model means for a platform pricing its own tenant isolation. Below is the full line-by-line breakdown — what the $25/month base plus per-tenant metering actually charges for, what the same isolation costs on hardware you own, and the specific traffic threshold where the answer flips.
What the $25/Month Base Fee Actually Includes
Workers for Platforms is the primitive behind any SaaS product that lets end customers run their own logic behind one shared control plane — a low-code builder, a website platform, an API middleware layer, anything where "one Worker script per tenant" is the isolation unit. Cloudflare's published pricing for it is a flat monthly fee plus three metered dimensions:
| Line item | Included in $25/month | Overage rate |
|---|---|---|
| Base plan | — | $25.00/month flat |
| Requests | 20,000,000/month | $0.30 per additional million |
| CPU time | 60,000,000 CPU-ms/month | $0.02 per additional million CPU-ms |
| Scripts (tenants) | 1,000 | $0.02 per additional script/month |
Two things stand out immediately. First, requests and CPU time are billed per unit consumed, not per tenant — a platform pays for what its tenants' code actually executes, the same way the underlying Workers Paid plan (a separate $5/month product) bills the base account. Second, the literal "per-tenant metering" in the title shows up in exactly one line: the $0.02/month charged per script once a platform passes 1,000 tenant scripts, since the common Workers for Platforms pattern is one deployed script per tenant.
Pricing the Workers for Platforms Bill at Three Scales
To see how those four line items add up in practice, model a platform at 50, 500, and 5,000 tenants, holding the workload constant: 100,000 requests per tenant per month, averaging 10ms of CPU time per request — a reasonable profile for a lightweight API endpoint doing a lookup and returning JSON. (CPU-ms per request is the one assumption doing real work in this model; a heavier tenant workload at 25ms/request would roughly 2.5x the CPU overage line at every scale below, though it doesn't change which platform wins, only by how much.)
| Tenants | Total requests | Total CPU-ms | Request overage | CPU overage | Script overage | Total bill | Per tenant |
|---|---|---|---|---|---|---|---|
| 50 | 5M | 50M | $0 (under 20M) | $0 (under 60M) | $0 (under 1,000) | $25.00 | $0.500 |
| 500 | 50M | 500M | $9.00 (30M over) | $8.80 (440M over) | $0 (under 1,000) | $42.80 | $0.086 |
| 5,000 | 500M | 5,000M | $144.00 (480M over) | $98.80 (4,940M over) | $80.00 (4,000 over) | $347.80 | $0.070 |
The per-tenant cost drops as the platform grows, from $0.50 down toward roughly $0.07 — that's the flat $25 base amortizing across more tenants, plus the fact that every overage rate is linear with no further volume discount. Push the model to a much larger scale and the per-tenant cost asymptotically approaches about $0.07 (the marginal cost of one tenant's usage with the $25 base fully amortized away): the request line converges to $0.03/tenant, the CPU line to $0.02/tenant, and the script line to a flat $0.02/tenant once past 1,000 scripts.
Pricing the Same Fleet as Kubernetes Namespaces on Hetzner
Self-hosting tenant isolation as Kubernetes namespaces removes the platform-for-platforms fee entirely — there's no separate charge sitting between a tenant's workload and the machine running it, only the box itself. This site's earlier Render-vs-Hetzner cost breakdown established a working density for always-on, low-traffic containers on Hetzner's CX line: roughly 150MB of actual RAM per lightweight process, with a CX23 (2 vCPU / 4GB, ~$6/month) comfortably holding 20 such processes and a CX43 (8 vCPU / 16GB, ~$17/month) holding "well over a hundred." Using a conservative 100 tenants per CX43 as the working density and pricing the same three tenant counts:
| Tenants | Boxes needed | Box type | Total bill | Per tenant |
|---|---|---|---|---|
| 50 | 1 | CX43 | $17.00 | $0.340 |
| 500 | 5 | CX43 | $85.00 | $0.170 |
| 5,000 | 50 | CX43 | $850.00 | $0.170 |
Unlike Workers for Platforms, this cost curve doesn't bend downward with scale — it's flat at $0.17/tenant from 500 tenants onward, because each CX43 reserves capacity for exactly 100 tenants whether they're idle or generating traffic. There's no fixed cost amortizing away, no metering that rewards low-traffic tenants: the box is sized for peak reserved memory, full stop.
The Side-by-Side, and Why It Flips
| Tenants | Workers for Platforms | Self-hosted (always-on) | Cheaper option | Ratio |
|---|---|---|---|---|
| 50 | $0.500/tenant | $0.340/tenant | Self-hosted | 1.5x |
| 500 | $0.086/tenant | $0.170/tenant | Workers for Platforms | 2.0x |
| 5,000 | $0.070/tenant | $0.170/tenant | Workers for Platforms | 2.4x |
At 50 tenants, self-hosting wins because a single underused CX43 is cheap in absolute terms and the $25 Cloudflare floor hasn't been earned back yet. Past that point, the two models diverge for a structural reason, not a pricing accident: Workers for Platforms bills for execution — CPU-ms actually spent handling a request — while an always-on Kubernetes namespace bills for reservation, the RAM set aside for a tenant whether or not it's doing anything. A tenant that's mostly idle costs Cloudflare almost nothing beyond its request count; that same idle tenant still occupies its full 150MB slice of a CX43 all month on the self-hosted side.
Where Scale-to-Zero Changes the Answer
That reservation-vs-execution gap is exactly what Kubernetes-native scale-to-zero tooling like KEDA exists to close — but it only closes it above a specific traffic threshold, and this workload sits well below it. KEDA's default cooldown period is 300 seconds: a pod only scales down to zero after five minutes with no active request. At 100,000 requests/tenant/month spread evenly across a 30-day month, the average interval between requests is about 26 seconds — far shorter than the 300-second cooldown, so a KEDA-managed pod for this tenant profile never actually idles long enough to scale down. It behaves exactly like the always-on model above, and the $0.17/tenant CX43 pricing holds.
The crossover point is a specific number worth naming: scale-to-zero only starts recovering resources once a tenant's average request interval exceeds 300 seconds, which works out to roughly 8,600 requests per month or fewer — about one request every five minutes. Below that line (a free-tier account someone checks in on once a day, a webhook receiver that mostly sits dark), self-hosted namespaces with scale-to-zero pull back ahead of Cloudflare's metering, since an idle pod at zero replicas costs nothing beyond the box's fixed price. Above it — which is where a paying, actively-used tenant on most SaaS products lives — the always-on reservation model stays the more expensive one, and Cloudflare's per-execution billing keeps its edge.
What the $25 and the Metering Are Actually Paying For
None of this makes the layered Cloudflare fee a bad deal even where it wins on raw compute cost — it's not just a markup on CPU-ms. That $25/month and the metering on top of it also buys a dispatch namespace that enforces per-tenant resource limits automatically, Cloudflare's edge network and DDoS protection in front of every tenant's traffic, and zero patching, scaling, or capacity-planning ops for the platform operator. A self-hosted Kubernetes namespace fleet gets the compute-cost advantage at low-traffic scale, or with scale-to-zero tuned to genuinely bursty tenants, but the platform team is the one operating the cluster, the ingress, and the isolation boundary between tenants — work Workers for Platforms performs as part of the fee.
The Actual Decision Rule
The honest takeaway isn't "self-host and save," and it isn't "Workers for Platforms is cheaper, full stop" either — it's that the two billing models charge for different things, and which one wins depends on a traffic number a platform team can actually measure: the average request interval per tenant. Steady, moderately-trafficked tenants (a request more often than every five minutes) are cheaper on Cloudflare's metered execution model past roughly 500 tenants. Genuinely sparse or bursty tenants — the long tail every multi-tenant SaaS product accumulates — are cheaper on a self-hosted, scale-to-zero-tuned Kubernetes namespace fleet, and stay that way regardless of tenant count, because an idle pod at zero replicas on hardware you already own costs nothing at all.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, where per-tenant isolation is a Kubernetes namespace the platform manages for you, not a metered line item on someone else's invoice. Star the repo on GitHub or deploy your first app today.



