Demo of Open-Source Static Site CMS in Rust: 400x faster than WordPress, 100x faster than Ghost
How to demo:
- create digitalocean VM in SF datacenter. 2 GB RAM, 1 vCPU
- run in a Docker container:
docker run -p 8080:8080 pagezest/pagezest:latest
- run in a Docker container:
- create digitalocean VM in NYC datacenter. 8 GB RAM, 4 vCPU
- Run "Apache Benchmark":
ab -n 15000 -c 1000 "http://$IP:8080/hello-world"
- Run "Apache Benchmark":
Manifesto: we believe website hosting can and should be either 1) free, or 2) max $12/year (same cost as domain). We want to start a revolution in blogging/CMS world to drop prices 10-100x from where they are in 2025.
We think it's possible since
- the leading CMS (Wordpress/Ghost) are done in very CPU+RAM heavy languages: PHP/Node.js, and
- static sites are much faster than dynamic sites.
- IMPORTANT: pagezest will support dynamic sites also!, but plugins are static + cacheable by default, which will make it much easier for users to generate pure static sites.
What we're showing today is a demo proving 10-100x cheaper blog hosting is possible. Here are the highlights:
- A web server in Rust, with a plugin system (in webassembly) that is amazingly 400x faster than Wordpress!
- TBH: didn't expect to end up THAT much faster than WordPress. I guess WordPress is truly super inefficient!
- Plugins written in Rust (could be Zig if you want to. We have a Zig example)
- Plugins that are static/cached by default, allows users to easily create static sites.
- Even with dynamic plugins, pagezest is 200x faster.
- Open sourced: github link
- Demo command:
docker run -p 8080:8080 pagezest/pagezest:latest
Benchmark table of of stats comparing PageZest with Wordpress and Ghost.
wordpress | ghost | pagezest (dynamic) | pagezest (static) | |
---|---|---|---|---|
RPS | 8.8 req/s | 25 RPS | 2000 RPS | 3800 RPS |
Why do we think web hosting can be free (or max $12/year)?
Because we're 400x faster than WordPress. So we think we can easily charge at least 100x cheaper. And current prices for web hosting are minimum $2.50/month.
Calculations for how much CPU time a medium-traffic blog needs:
- 50,000 sessions/month (the monthly minimum to qualify for Mediavine).
- Each session takes up around 50 requests to the server
- So, per month, that's 2.5 million requests per month.
- PageZest can handle 3800 requests/second.
- CPU time, then, is around 658 seconds, or just 11 minutes of compute time.
- 14 minutes! I think we can easily give that away for free!
How would Wordpress compare?
- Wordpress, with zero plugins, handles 10 requests/second.
- add in plugins, like WooCommerce, and Wordpress slows way down.
- So, Wordpress would need 400x more CPU time.
- 400 * 11 minutes is......4400 minutes, or 73 hours, or 3 days!!!
- Doing the math: a 2 GB RAM server can only really host around 10 medium traffic (zero-plugin) Wordpress sites, while PageZest can easily handle 4000 sites!!! On only 2 GB of RAM!!
How we benchmark PageZest against Wordpress and Ghost
Hardware requirements:
- 2 GB RAM, 1 vCPU VM used for all tests. No SSL setup. Located in DigitalOcean's SF datacenter.
- IMPORTANT: need yet one more VM to run benchmark from. We used a 8 GB RAM, 4 vCPU server in DigitalOcean's NYC datacenter.
- DO NOT run Apache Benchmark from your own home network!! As we found out the hard way, my ISP was rate-limiting the number of open connections I could have. During development, couldn't get over 200 RPS. Once we tested on a DigitalOcean server, we immediately got over 650 RPS. 3800 RPS was later achieved with more optimizations.
We used Apache Benchmark (ab) to measure request per second:
- These are the ab parameters we used for wordpress+ghost
ab -n 1000 -c 16 "$URL"
- Because PageZest was so much faster, we needed to increase the parameters significantly in order to fully saturate the CPU:
ab -n 15000 -c 1000
http://$IP:8080/hello-world
Wordpress
- Setup using DigitalOcean image
- this means we run this benchmark on a Wordpress with 0 plugins.
- Usually Wordpress will have 10-20 plugins ==> significantly smaller request/second. See Kinsta's numbers.
- Woocommerce, even worse.
- Run:
ab -n 1000 -c 16 "http://$IP/index.php/2025/05/03/hello-world/
Ghost
- Setup using DigitalOcean image
- Run:
ab -n 1000 -c 16 http://$IP/hello-world/
PageZest
- Easiest way is probably to run PageZest as a Docker container:
docker run -p 8080:8080 pagezest/pagezest:latest
. - Run:
ab -n 15000 -c 1000 "http://$IP:8080/hello-world"
How did we engineer PageZest to be 400x faster than Wordpress?
Just a few major technical decisions was responsible for 400x faster.
- For static PageZest website, the biggest one was simply making plugins static/cacheable by default.
- We are aiming to design plugins like React components – if the input didn't change, then the output didn't change, and we cache based on a hash of the input.
- For dynamic PageZest websites, the biggest one was: NO JSON!!! Using FlatBuffers (zero-parse step!!)
- for dynamic pages, this was the biggest speedup by far, amazingly. There's a good reason why Google uses FlatBuffers for their internal RPC system instead of JSON. Parsing JSON requires a significant amount of mallocs, and malloc is a very non-trivial implementation.
- Rust!! (Not PHP). Self-explanatory. You can look at any one of the many programming language benchmarks. Rust floors PHP, every time. 5-10x faster.
- WebAssembly for plugins.
How static/cacheable plugins work
This deserves a brief explanation because I think it's quite cool:
- Inspired from React components.
- Similar to React's useEffect API.
- An "input" attribute specified in the plugin's manifest JSON.
- By default, plugins are static/cacheable.
- there will be an attribute that plugin writers can specify, to disable caching of the plugin. Like "disable_cache: true".
- If the input didn't change, then output didn't change.
- so take a hash of the input.
- use the hash to map hashtable from input to output.
- Concrete example:
- input could be: "URL", or "URL param"
- the output of the plugin would be the same every time for that URL.
Why static/cacheable plugins are really useful
Because most of the top Wordpress plugins can be easily static/cached
- Yoast SEO: output is almost always the same for a given URL
- Translation plugins: same.
- Cookie banner for consent
- Google analytics plugin
- custom HTML blocks.
- WPForms
- Any webpage widget
How are the files structured in PageZest:
- pagezest: a single binary with the dashboard (pz-admin) files compiled into it.
- plugins/ directory
- toc/ directory
- toc.wasm
- footer/ directory
- footer.wasm
- toc/ directory
Optimizations that did NOT help PageZest become much faster
It was quite instructive and surprising to us what didn't help. We'll write these down to help other learn:
- Using the filesystem to store blog posts instead of sqlite.
- actually, this resulted in a big performance regression from 2200 RPS to 400 RPS.
- the performance regression was due to the blog posts no longer being cached in memory. So each request was now reading from the filesystem. Lots of syscalls. Very slow.
- as it turns out, sqlite was caching relevant rows in memory.
- using actix web server instead of tiny-http
- we thought actix and tokio's green threads would help.
- Since we are benchmarking on a 1 vCPU VM, it didn't really help.
Can PageZest be made even faster?
Yes, but not that much faster. The theoretical maximum we found was 6500 RPS, using Anton's basic actix server he used for his own benchmarking youtube video. PageZest is already at 3600-3800 RPS. The main speedup I see is if PageZest cached the whole page in-memory instead of only static plugin output. Then static PageZest sites could deliver 6000+ RPS.
What's next for PageZest?
We want to launch a managed hosting service, with a generous free tier (your own custom domains allowed!). If you are interested, please sign up to the PageZest email list (see bottom of this webpage). Email List signups are the primary way we evaluate whether people are really interested in what we are doing.
Feature-wise, we want to release good looking themes so people can have decent looking websites.