Ghost vs WordPress on One VPS: The Speed Gap Is Page Weight, Not the Engine
Published 6 September 2026. Ghost 5 and WordPress were measured on the same 2 vCPU, 7.8 GiB VPS, against the same MySQL 8 instance, serving the same article — this one — with the same nginx cache in front of each. Every request in this article went over plain HTTP on loopback, so TLS handshakes could not distort the comparison. Ghost was removed afterwards and Docker returned to zero containers.
1. The Result, and Why the Usual Number Is Misleading
Every Ghost-versus-WordPress comparison reports requests per second, and by that measure Ghost wins convincingly. Here is what we measured, both serving an identical 26 KB article body:
| Configuration | Req/s | P50 | P95 | Page served |
|---|---|---|---|---|
| Ghost, no cache | 47.6 | 202 ms | 284 ms | 42.5 KB |
| WordPress, no cache | 15.4 | 632 ms | 859 ms | 144.6 KB |
| Ghost + nginx cache | 8,518 | 1 ms | 2 ms | 42.5 KB |
| WordPress + microcache | 5,916 | 2 ms | 3 ms | 144.6 KB |
Uncached, Ghost serves 3.1 times more requests. That is the number that gets quoted, and on its own it is true. It is also nearly meaningless, because the two systems are not delivering the same amount of work per request. Ghost’s page is 42.5 KB; WordPress’s is 144.6 KB — 3.4 times larger for the same article text.
Convert both to bytes of HTML generated per second and the gap disappears:
| Uncached | Requests/s | Page size | HTML generated |
|---|---|---|---|
| Ghost | 47.6 | 42.5 KB | 1.9 MB/s |
| WordPress | 15.4 | 144.6 KB | 2.1 MB/s |
Within 9% of each other. On this hardware, Node and PHP-FPM produce dynamic HTML at approximately the same rate — around two megabytes a second. Ghost’s advantage in the request count is not a faster template engine. It is a smaller page.
our first comparison was worse than misleading, it was wrong. We benchmarked Ghost’s stock “About this site” page — 1 KB of content — against a 26 KB technical article on WordPress, and Ghost looked 4.6 times faster. Injecting the identical article body into Ghost’s database and re-running dropped that to 3.1×, and converting to bytes removed it entirely. A benchmark that does not control the payload is measuring the content, not the platform.
Where the extra 100 KB comes from
It is worth being precise about what that page weight is, because it is not a WordPress tax. Our WordPress theme emits a table of contents, a sidebar, a floating toolbar and a JSON search index inlined into every article page. Ghost’s default theme emits none of those. Swap in a minimal WordPress theme and the page shrinks; add those features to Ghost and it grows.
Which is the honest version of the conclusion: you are choosing between two themes and two feature sets, not between two speeds.
2. Caching Erases the Question Entirely
Both figures above are for uncached requests, which on a content site is the rare case. With a cache in front, both platforms move into a range where the application is no longer doing any work:
| Platform | Uncached | Cached | Multiplier |
|---|---|---|---|
| WordPress | 15.4 req/s | 5,916 req/s | 384× |
| Ghost | 47.6 req/s | 8,518 req/s | 179× |
The 3.1× platform difference is a rounding error next to a 384× caching difference. This matches what we found benchmarking seven applications on this same server: caching is the only lever with an order of magnitude in it, and everything else is noise by comparison.
Measured in bytes again, cached WordPress delivers 816 MB/s against Ghost’s 346 MB/s — nginx is serving larger files from the same cache, so it moves more data. At this point neither number describes the platform; both describe nginx and the network stack.
If your site is public and mostly read by anonymous visitors, the platform choice has no measurable effect on speed. It matters for pages that cannot be cached — member content, logged-in views, personalised pages — and that is the only place the 3.1× is real.
3. Ghost Ships With Caching Disabled, and Does Not Tell You
Our first attempt to put nginx in front of Ghost produced a cache that never hit. Every response came back X-Cache: MISS, and throughput was lower than hitting Ghost directly — 57.7 requests per second against 75.5, because we had added a proxy hop for nothing.
The reason is in Ghost’s response headers:
$ curl -sI http://127.0.0.1:2368/about/
HTTP/1.1 200 OK
X-Powered-By: Express
Cache-Control: public, max-age=0
ETag: W/"4242-9YSkZM1N/smZ6wQo53D1Oa0++4M"max-age=0 instructs every cache in the path — nginx, Varnish, Cloudflare — to revalidate before serving. Ghost is asking not to be cached, and well-behaved caches obey. The fix is one directive:
location / {
proxy_pass http://127.0.0.1:2368;
proxy_set_header Host $host;
proxy_cache GHOST;
proxy_cache_valid 200 301 302 10m;
proxy_cache_lock on;
# Without this, Ghost's "max-age=0" defeats the cache entirely
proxy_ignore_headers Cache-Control Expires;
add_header X-Cache $upstream_cache_status;
}That single line took Ghost from 57.7 requests per second to 8,518. It is the difference between the two extremes of the whole comparison, and nothing in Ghost’s interface indicates that it is needed.
ignoring Cache-Control is a blunt instrument. It also caches responses Ghost had good reason to mark uncacheable — member-only content, previews, anything personalised. If you run Ghost memberships, exclude those paths from the cache explicitly rather than ignoring the header globally, or logged-in readers will be served each other’s pages.
4. What Each One Costs to Run
| Resource | Ghost 5 | WordPress |
|---|---|---|
| Application memory | 201 – 236 MiB (Node) | 54 MiB (PHP-FPM, all pools) |
| Disk, application | 1.6 GB (Docker image + container) | 238 MB |
| Database size | 2.6 MB | 4.2 MB |
| Database tables | 75 | 39 |
| Cold start to first 200 | 11.6 s | Effectively none (FPM pool is resident) |
| Database requirement | MySQL 8 mandatory | MySQL or MariaDB |
This is the part of the comparison where the direction reverses, and it is not close. Ghost uses roughly four times the memory and nearly seven times the disk. The 1.6 GB is the Docker image and container layer; installing Ghost from npm rather than Docker is smaller, but then you own the Node version management.
The 54 MiB for PHP-FPM deserves a caveat: that is the resident set of the worker pool, which grows under concurrency and shrinks when workers recycle. It is a fair steady-state figure on a low-traffic site, not a ceiling.
Ghost 5 also requires MySQL 8 in production — SQLite is supported for development only. On a VPS that means either a second database engine or sharing the one you already run, which is what we did here. That is worth knowing before you plan a 1 GB server around it.
5. What the Numbers Do Not Decide
Having measured all of it, the performance case for switching is weak. A cached WordPress site and a cached Ghost site are both faster than any content site needs, and uncached they generate HTML at the same rate. If speed is the reason you are considering a migration, the benchmark does not support it.
The real differences are structural:
- Ghost has memberships and newsletters built in. On WordPress that is a plugin stack, and plugin stacks are where WordPress performance actually goes to die — not in the core.
- WordPress has an ecosystem. Whatever you need to add, someone has already built it. With Ghost you will write it or do without.
- Ghost’s admin is a single coherent application. WordPress’s is thirty plugins with thirty opinions about where their settings live.
- Ghost’s editor is better. This is subjective and it is also the reason most people actually switch.
Choose on those. The requests-per-second figure that dominates this comparison online turns out, when you control the payload, to be measuring how much HTML two themes emit.
6. Frequently Asked Questions
Is Ghost faster than WordPress?
Uncached, Ghost served 47.6 requests per second against WordPress’s 15.4 on identical hardware and content. But Ghost’s page was 3.4 times smaller, and measured in HTML generated per second the two were within 9% of each other. The speed difference is page weight, not engine speed.
How much RAM does self-hosted Ghost need?
We measured 201 to 236 MiB for the Ghost Node process, against 54 MiB for the PHP-FPM pool serving WordPress. Ghost also requires MySQL 8, so budget for the database separately. A 1 GB VPS runs Ghost, but with less headroom than the same server running WordPress.
Why is my Ghost site not being cached by nginx or Cloudflare?
Ghost sends Cache-Control: public, max-age=0, which tells every cache to revalidate before serving. Add proxy_ignore_headers Cache-Control Expires to your nginx location block. In our test that took throughput from 57.7 to 8,518 requests per second, a factor of 148. Exclude member and preview paths first, or logged-in readers may be served each other’s cached pages.
Does Ghost work with SQLite in production?
No. Ghost 5 supports SQLite for development only and requires MySQL 8 for production installs. On a VPS this means running MySQL alongside Ghost, or pointing Ghost at a database instance you already operate, which is what we did to keep this comparison on equal footing.
Should I migrate from WordPress to Ghost for performance?
Our measurements do not support that reason. Cached, both platforms exceeded 5,900 requests per second on a 2 vCPU server, far beyond what a content site needs. Migrate for the editor, built-in memberships or a simpler admin. Do not migrate expecting a speed gain a cache would have given you anyway.
7. The Short Version
- Uncached: Ghost 47.6 req/s, WordPress 15.4 — but ~2 MB/s of HTML each. The gap is page size.
- Cached: 8,518 and 5,916 req/s. Both irrelevant to any real content site.
- Caching multiplied WordPress by 384× and Ghost by 179×. Nothing else comes close.
- Ghost costs 4× the RAM and 7× the disk, and requires MySQL 8.
- Ghost sends
max-age=0; withoutproxy_ignore_headersyour cache does nothing.
For the caching configuration on the WordPress side, our production setup guide covers the nginx and PHP-FPM tuning used here, and the capacity model puts both of these numbers next to five other applications on the same machine.