How to cache ghost posts?

I ran a benchmark using `ab -r -n 1000 -c 10 https://
just by running this several mysql processes came up and whole website was slowed down.

Config: Digital ocean

I think there needs to be a caching layer(from my side) on top of ghost which can do full page cache and avoid database hits.
Can someone provide me some info on this?

Varnish is great for caching content. You can configure varnish to never cache API / Admin requests, but listen to those requests since they have cache invalidation headers

Do you have any hardware recommendations for using Varnish? Do you cache in memory or on disk?

As far as I’m aware, Varnish supports both in-memory and disk storage for caches. You don’t need powerful hardware to run Varnish; a $5 DO droplet with Ghost and Varnish should be adequate.

Yes it does, I was curious what your implementation choices were.

a $5 DO droplet with Ghost and Varnish should be adequate.

That’s good to know, as that’s the droplet I’m using right now and I wanted to cache in memory but was concerned that this tier of droplet wouldn’t have enough memory.

You can always use swap if needed. I configured Varnish on my site (which isn’t very active) a couple years ago, and I manually purge caches when I update posts since that doesn’t happen often.

As an aside, all of this discussion is relative to size; if you have thousands of posts, a $5 droplet probably won’t suffice.

Yeah I guess I’ll just have to give it a try and watch memory consumption. I’ll have to look into how to use swap on a DO droplet.

I used caddy server on top of Ghost. It’s cache mechanism did increased my website req/s. I did full page cache but I can’t flush cache or avodi homepage cache.

Can I do that in varnish without getting into terminal?
And do you prefer ghost + nginx + varnish or just ghost + varnish?

Not that I’m aware. Varnish uses a compiled configuration mechanism and I think you need terminal access to make changes. Questions like these are better suited for your host.

My configuration is ghost->varnish->nginx but as far as I’m aware, varnish is capable of serving as a web server

@vikaspotluri123 do you have an example of your Varnish config files? I’m trying to setup Varnish on a DO droplet running Nginx.

It’s been a long time since I configured this (including before Memberships was a thing in Ghost), and I am not very experienced with Varnish, but here’s a majority of the config:

# This is an example VCL file for Varnish.
# It does not do anything by default, delegating control to the
# builtin VCL. The builtin VCL is called when there is no explicit
# return statement.
# See the VCL chapters in the Users Guide at
# and for more examples.

# Marker to tell the VCL compiler that this VCL has been adapted to the
# new 4.0 format.
vcl 4.0;

# Default backend definition. Set this to point to your content server.
backend default {
    .host = "";
    .port = "80";

backend ghost {
    .host = "";
    .port = "2372";

sub vcl_recv {
    if (req.method == "PURGE") {
        return (purge);

    # Happens before we check if we have this in cache already.
    # Typically you clean up the request here, removing cookies you don't need,
    # rewriting the request, etc.

    if ( == "") {
        set req.backend_hint = ghost;

    if ( req.url !~ "/ghost/" && req.url !~ "/p/" ) {
        unset req.http.cookie;

sub vcl_backend_response {
    # Happens after we have read the response headers from the backend.
    # Here you clean the response headers, removing silly Set-Cookie headers
    # and other mistakes your backend does.

    set beresp.ttl = 5m;

sub vcl_deliver {
    # Happens when we have all the pieces we need, and are about to send the
    # response to the client.
    # You can do accounting or modifying the final object here.

   if ( req.url ~ "/ghost/" || req.url ~ "/signout" || req.url ~ "/p/" ) {
        set resp.http.Cache-Control = "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0";
        set resp.http.expires = "0";

    if (obj.hits > 0) {
        set resp.http.X-Cache = "HIT";
    } else {
        set resp.http.X-Cache = "MISS";

    set resp.http.X-Proxy-Cache = "1";

Just as an aside; Ghost minimum requirements state it needs at least a 2GB RAM, so $5 DO Droplets won’t cover it. It needs to be the $10 one’s at bare minimum.

Where do you see that? It says 1gb here:

That’s odd, I swore I read somewhere it was 2GB. My apologies if that’s not the case.