Skip to content

Build1 publisher3 min readPublished

Two vCPUs rendered 5,000 separately editable sites at 150 requests a second

Kooboo shipped the request-level CSVs and the provisioning script behind a ten-minute run that averaged 45.6% CPU, so the interesting question is no longer the headline but which of its conditions your own tenants share.

The Engineer · Build desk

Photograph accompanying Two vCPUs rendered 5,000 separately editable sites at 150 requests a second
Photo: github.com

What happened

  • Kooboo cloned one site package into 5,000 separate Kooboo sites on a small 2-vCPU, 4 GB Tencent Cloud VPS, then drove 90,000 HTTPS requests at them from a separate Alibaba Cloud server over the public Internet.
  • The ten-minute run held a target of 150 request starts per second and ended with 89,969 verified responses against 31 connection timeouts, which Kooboo reports as a 99.97% first-attempt success rate.
  • Monitoring recorded average CPU consumption at 45.6% of the two-vCPU machine, a sampled peak of 81.5%, and resident memory peaking at approximately 2.50 GiB.
  • Only the Header View used Kooboo's cache-by-purpose setting and there was no full-page output cache, so the root page ran its ten-entry blog query and rendered afresh on every request.
  • The repository accompanying the write-up carries the test client, request-level CSV data, server monitoring records and reproduction instructions.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • capability About half a megabyte of resident memory per tenant site is the figure to beat if your multi-tenant plan is a container or a worker pool per customer, because that is the per-tenant overhead a shared-process design declines to pay.
  • constraint Holding the offered rate fixed measures headroom at one load and leaves the saturation point unlocated, so no density ceiling can be quoted from this data without a ramped run to back it.
  • decision Anyone reusing the figure has to judge how far their tenants' templates and content diverge from identical clones, since divergence is what grows the working set the 4 GB has to hold.
  • precedent Publishing request rows, monitoring records and the provisioning script raises the bar for the next hosting-density claim, which now has to arrive with material an outsider can attack.

45.6% of two vCPUs [5] is 0.912 vCPU-seconds of CPU spent per wall-clock second. Divide that by 150 responses per second and each response cost roughly 6.1 ms of CPU [2]. The post enumerates what that budget has to cover: domain resolution, Kooboo site selection, routing, layout and view rendering, the uncached home-page content query, HTML generation and response transfer [11]. The requests arrived over HTTPS from a separate cloud, across the public Internet, not over loopback [1].

The arithmetic closes. A target of 150 starts per second for ten minutes is 90,000 requests, and 89,969 verified responses plus 31 connection timeouts is exactly 90,000 [1]. Nothing went missing between the generator and the summary table.

Two other divisions carry more weight than the headline. Resident memory peaked near 2.50 GiB across 5,000 sites, about 0.51 MiB per site [3], and because that total includes the runtime baseline the marginal cost per site is lower than that. And 150 requests per second spread across 5,000 hostnames is 0.03 requests per second per site, about 18 requests per site over the whole run [4]. That is the traffic shape of long-tail hosting, which is the honest workload for 5,000 small sites, but it means no individual site was ever hot.

The run does not locate a ceiling, and it was not built to. The generator held a fixed target rate [3] rather than ramping until failures climbed. Sampled peak CPU was 81.5% against the 45.6% average [5], a peak-to-average ratio near 1.8, and scaling the offered rate by 100/81.5 would put sampled peaks at the two-vCPU wall somewhere near 184 requests per second [5]. That is arithmetic on two sampled numbers rather than a measurement. The 31 failures were connection timeouts [4], which points at connection handling rather than the render path.

What would have to be true for this density to transfer is the harder question, and Kooboo is straight about part of it. All 5,000 sites came from one imported package, which held page structure, content volume, query shape and response size constant, and the post says that choice creates an important limitation [13]. Five thousand sites that launched with the same ten AI-written articles [9] are the cheapest five thousand sites anyone will ever host. Real tenants diverge in template count, content volume and query shape, and divergence is what stops a shared working set from staying small. The benchmark also requested only root pages, so the article-detail routes shipped inside the package went unexercised [11].

The parts of this I would keep are the verification and the cache configuration. Each clone carries a visible marker such as Site 4996, and the client checked for the expected marker in every body, on the grounds that a 200 cannot prove 5,000 hostnames reached 5,000 correct site bindings [12]. Only the Header View is configured with cache-by-purpose and there is no full-page output cache [10], so the measured work is rendering rather than a cache read. The isolation claim, that all 5,000 share one server process while each keeps its own editable site record [8], is the one thing a CSV cannot demonstrate, and Kooboo is offering technical reviewers temporary access to edit an assigned site and watch what happens [14].

What to watch

  • The promised downloadable site package, which is what would let an outsider reproduce the run on hardware Kooboo does not control.
  • A ramped saturation run rather than a fixed request rate, which is the only design that would produce an actual density ceiling.
  • Reports from reviewers granted temporary edit access, in particular whether changing one assigned site leaves the other 4,999 untouched.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories