← Back to blog

2026-06-04 · 11 min read

Case Study: Scaling a Multi-Tenant Platform to 5,000+ Sites on Cloud Run & Cloudflare

How I designed and operated a multi-tenant hosting platform on Google Cloud Run, fronted by Cloudflare, that serves 5,000+ sites globally, fast, secure, auto-scaling, and load-tested to grow well beyond that.

#gcp#cloud-run#cloudflare#case-study#serverless#cdn#scalability
Case Study: Scaling a Multi-Tenant Platform to 5,000+ Sites on Cloud Run & Cloudflare

Case Study: Scaling a Multi-Tenant Platform to 5,000+ Sites on Cloud Run & Cloudflare

This is a detailed look at a platform I designed and operate that hosts 5,000+ sites on Google Cloud Run, fronted by Cloudflare for global delivery and security. It auto-scales, stays fast worldwide, and was load-tested to handle well beyond its current footprint. Specifics are generalised for confidentiality, but the architecture, decisions, and results are real.

The problem

The goal was to host a large and growing number of sites, thousands of them, with these constraints:

  • Cost had to scale with usage, not with peak. Running thousands of always-on VMs or containers would be ruinous; most sites are idle most of the time.
  • Global performance. Visitors are everywhere; pages had to be fast regardless of region.
  • Security by default. Thousands of public endpoints is a large attack surface: DDoS, bots, and abuse had to be handled without per-site effort.
  • Operability. A small team couldn't babysit thousands of sites. Provisioning, TLS, and scaling had to be automated and hands-off.

Why Cloud Run

The breakthrough decision was Google Cloud Run as the compute layer. For a fleet of mostly-idle sites, serverless containers are close to ideal:

  • Scale to zero. A site that gets no traffic costs (almost) nothing. You pay for requests, not for idle capacity, exactly right when most of 5,000 sites are quiet at any moment.
  • Automatic scaling. When a site gets a traffic spike, Cloud Run scales its container out automatically and back down after, no capacity planning per site.
  • No servers to manage. No node pools, no patching, no autoscaler tuning. The team operates the platform, not the machines.
  • Fast cold starts with min-instances tuning where latency mattered most.

The architecture

   Visitors (global)
        │  HTTPS
        ▼
 ┌──────────────────────────────┐
 │   Cloudflare (edge)           │   CDN cache · WAF · DDoS · bot mgmt · TLS
 │   - caches static assets      │
 │   - terminates TLS            │
 │   - rules per hostname        │
 └──────────────┬───────────────┘
                │  origin (authenticated)
                ▼
 ┌──────────────────────────────┐
 │   Google Cloud Run            │   container per service · scale to zero · autoscale
 │   - multi-tenant routing      │
 └──────────────┬───────────────┘
                │
   ┌────────────┼─────────────┬───────────────┐
   ▼            ▼             ▼               ▼
 Cloud SQL   Cloud Storage  Secret Mgr   Cloud Logging /
 (data)      (assets)       (secrets)    Monitoring (o11y)


   Delivery pipeline:
   GitHub (source) ──▶ Cloud Build (CI/CD) ──▶ Artifact Registry ──▶ Cloud Run

See the architecture diagram at the top of this post for the full picture.

The pieces:

  • GitHub holds the source of truth for application code and infrastructure.
  • Cloud Build is the automation pipeline: a push to GitHub triggers a build that tests the code, builds the container image, pushes it to Artifact Registry, and deploys to Cloud Run, no manual steps.
  • Cloudflare at the edge: a global CDN that caches static content close to users, plus WAF, DDoS protection, bot management, and TLS, applied across all hostnames without per-site config.
  • Cloud Run as the origin: containers that scale to zero when idle and out on demand.
  • Cloud SQL for relational data, Cloud Storage for assets/media, Secret Manager for credentials, and Cloud Logging/Monitoring for observability.
  • Infrastructure as Code so a new site's resources are provisioned consistently and repeatably.

Key decisions and reasoning

1. Edge-first: let Cloudflare absorb the load

The single biggest performance and cost lever was caching aggressively at Cloudflare. Most requests for most sites are for cacheable content, serving those from the edge means they never hit Cloud Run at all. That:

  • Cuts origin cost (fewer Cloud Run invocations),
  • Makes sites fast globally (served from the nearest edge), and
  • Shields the origin from traffic spikes and attacks.

2. Security applied once, everywhere

Rather than securing 5,000 sites individually, security lives at the edge: WAF rules, DDoS mitigation, bot management, and forced HTTPS apply across the whole fleet. Origin access is locked so traffic can only reach Cloud Run through Cloudflare, no bypassing the edge.

3. Scale to zero as a cost strategy

With thousands of mostly-idle sites, scale-to-zero isn't a nice-to-have, it's the economic model that makes the platform viable. You're not paying for 5,000 running containers; you're paying for the requests that actually arrive.

4. Load-tested before it mattered

I load-tested the platform to validate it scales well beyond the current 5,000 sites, simulating traffic surges across many tenants, confirming Cloud Run's autoscaling behaviour, checking Cloudflare cache hit ratios, and finding the limits before production found them. Capacity is a measured fact here, not a hope.

5. Fully automated delivery with GitHub + Cloud Build

Every change flows through code, not consoles. Source lives in GitHub; a push triggers Cloud Build, which tests, builds the container, pushes it to Artifact Registry, and deploys to Cloud Run. This means:

  • Repeatable, auditable releases: every deploy traces back to a commit.
  • No manual steps: the pipeline is the only way to ship, so it's consistent across all tenants.
  • Fast rollback: redeploy a previous image tag from the build history.

The hard parts

  • Cold starts. Scale-to-zero means the first request after idle can be slow. I tuned min-instances for latency-sensitive tenants and relied on edge caching to absorb the rest.
  • Multi-tenant routing. Mapping thousands of hostnames cleanly to the right service, with TLS for each, took careful automation.
  • Cache correctness. Aggressive caching is great until someone updates a site and sees stale content. Getting cache rules and invalidation right per content type was fiddly but essential.
  • Cost attribution. Understanding which tenants drove cost required good labelling and monitoring.

The outcomes

DimensionResult
Sites hosted5,000+ (and headroom proven by load testing)
PerformanceGlobal low-latency via Cloudflare edge cache
AvailabilityEdge-protected; origin shielded from spikes and attacks
Cost modelScales with traffic, not site count (scale-to-zero)
SecurityWAF, DDoS, bot management, forced TLS across the whole fleet
OperationsHands-off provisioning, autoscaling, and TLS

What I'd tell another team

  1. Put a CDN/edge in front of everything. It's the highest-leverage decision for performance, cost, and security simultaneously.
  2. Serverless shines for spiky, mostly-idle, many-tenant workloads. Cloud Run's scale-to-zero is what makes thousands of sites economically sane.
  3. Secure at the edge, once. Don't try to harden thousands of origins individually.
  4. Load-test for the future you're selling. "Supports 5,000 and scales beyond" should be a tested statement, not a marketing one.

This is the kind of cloud platform work I do, designing for scale, cost, and security from day one.

💡 Want the runnable version? I open-sourced a slimmed-down reference of this architecture, cloud-run-cloudflare-platform, with Terraform for Cloud Run + Cloudflare and a Cloud Build CI/CD pipeline.


Need a platform that scales cleanly and stays cheap and secure? That's my work, see my services or get in touch.

Share:LinkedInXWhatsApp

Related articles

Reactions & comments