How to Cache Your Ghost Blog with Cloudflare (Updated for 2026)
Caching your Ghost blog with Cloudflare can reduce Time to First Byte (TTFB) by up to 81% and cut origin server requests by 95%, according to Cloudflare's own benchmarks. This guide covers Ghost's built-in cache settings, Cloudflare's new Cache Rules (replacing the deprecated Page Rules), and automated cache purging with Workers.
Why should you cache your Ghost blog with Cloudflare?
Ghost is a Node.js application that generates HTML dynamically on each request. Without caching, every visitor triggers a fresh database query and template render on your origin server. For a blog that only changes when you publish or edit content, this is wasteful.
Cloudflare operates over 330 data centers worldwide. When you cache your Ghost blog at the edge, visitors receive content from the nearest Cloudflare server instead of your origin. According to Cloudflare community benchmarks, properly configured edge caching delivers:
- TTFB reduction of 66-81% — typical drops from 500ms+ down to under 100ms
- Cache hit rates of 80-90% — up from the default 30% without optimization
- Origin server load reduced by 60-90% — fewer requests hitting your Ghost instance
- LCP improvements of up to 50% — Largest Contentful Paint dropping from 3.8s to 1.9s in documented cases
For self-hosted Ghost blogs on modest hardware (DigitalOcean droplets, Hetzner VPS), this can mean the difference between a site that struggles under traffic spikes and one that handles them effortlessly.
How do you enable caching in Ghost's config file?
Ghost's built-in caching controls HTTP cache headers sent to browsers and CDNs. You configure this in your config.production.json file, typically located at /var/www/ghost/config.production.json for standard installations.
Add the caching section to your config file:
{
"url": "https://yourblog.com",
"database": {
"client": "mysql"
},
"caching": {
"contentAPI": {
"maxAge": 60
},
"frontend": {
"maxAge": 600
}
}
}Here's what each setting controls:
| Setting | What It Caches | Recommended Value | Effect |
|---|---|---|---|
contentAPI.maxAge |
Ghost Content API responses (JSON) | 60 seconds | Sets Cache-Control: public, max-age=60 on API responses |
frontend.maxAge |
HTML pages rendered by Ghost | 600 seconds (10 min) | Sets Cache-Control: public, max-age=600 on page responses |
After saving the file, restart Ghost for changes to take effect:
ghost restartImportant: These settings only add Cache-Control headers to Ghost's responses. They tell Cloudflare (and browsers) how long to cache content, but Cloudflare still needs to be configured to respect these headers — which brings us to the next step.
Should you use Redis for Ghost's internal cache?
By default, Ghost stores its internal cache in memory. For high-traffic sites, Ghost's official documentation recommends using the built-in Redis cache adapter. Redis persists cache across Ghost restarts and doesn't compete with your Node.js process for RAM.
This is separate from Cloudflare caching — Ghost's internal cache handles things like image size calculations and frequently accessed data, while Cloudflare caches the full HTTP response at the edge.
What is the difference between edge cache and browser cache?
Understanding this distinction is critical for configuring your caching strategy correctly.
| Cache Type | Where It Lives | Who It Helps | TTL Control |
|---|---|---|---|
| Browser Cache | On each visitor's device | Returning visitors only | Cache-Control: max-age header |
| Edge Cache | Cloudflare's 330+ global data centers | All visitors in that region | Edge Cache TTL setting in Cache Rules |
Edge caching is the bigger win. When a visitor in Tokyo requests your blog, Cloudflare serves the cached version from its Tokyo data center instead of routing the request to your origin server in, say, New York. The first visitor to that edge location triggers a cache fill, and every subsequent visitor in that region gets the cached version instantly.
Browser caching only helps when the same person revisits your site. Edge caching helps every visitor in an entire geographic region.
How do you set up Cloudflare Cache Rules for Ghost? (Replaces Page Rules)
Important 2025 update: Cloudflare deprecated Page Rules and replaced them with dedicated Cache Rules. If you're following older tutorials that reference Page Rules, switch to Cache Rules instead — they offer more granular control and higher limits.
Here's how to configure Cache Rules for your Ghost blog:
Step 1: Create a cache rule for public content
- Log in to your Cloudflare dashboard
- Select your domain
- Navigate to Caching → Cache Rules
- Click Create rule
- Name it: "Cache Ghost public pages"
- Set the expression:
(not starts_with(http.request.uri.path, "/ghost/")) and (not starts_with(http.request.uri.path, "/p/")) - Under Cache eligibility, select Eligible for cache
- Set Edge TTL to 2 hours (7200 seconds)
- Click Deploy
This rule caches all public pages while excluding the Ghost admin panel (/ghost/) and preview links (/p/).
Step 2: Create a bypass rule for the admin panel
- Create another Cache Rule
- Name it: "Bypass cache for Ghost admin"
- Set the expression:
(starts_with(http.request.uri.path, "/ghost/")) - Under Cache eligibility, select Bypass cache
- Click Deploy
This ensures your admin dashboard, editor, and authentication always hit the origin server directly.
Why Cache Rules instead of Page Rules?
According to Cloudflare's migration guide, Cache Rules provide several advantages over the legacy Page Rules system:
- Higher rule limits — Free plans get 10 Cache Rules vs. 3 Page Rules
- More granular matching — Use field-based expressions instead of simple URL patterns
- Stackable rules — Multiple Cache Rules can apply to the same request (Page Rules used first-match-wins)
- Better performance — Evaluated more efficiently at the edge
How do you automate cache purging when content changes?
The biggest challenge with aggressive caching is stale content. When you publish or update a post, Cloudflare continues serving the old cached version until the TTL expires.
The solution: use a Cloudflare Worker that automatically purges cache when Ghost publishes or updates content. Here's how it works:
- Create a custom integration in Ghost Admin under Settings → Integrations
- Add a webhook that fires on
post.publishedandpost.updatedevents - Point the webhook at a Cloudflare Worker URL
- The Worker calls Cloudflare's Cache Purge API to invalidate the changed page
To set up the Worker, you'll need a Cloudflare API token with Zone.Cache Purge permission. This approach gives you the best of both worlds: aggressive caching with 2-hour TTLs for performance, plus instant updates when you publish new content.
How do you verify that caching is working?
Method 1: Using curl in the terminal
Run this command to check cache headers:
curl -svo /dev/null https://yourblog.com/ 2>&1 | grep -i "cf-cache-status\|age:\|cache-control"Look for these headers in the response:
| Header | Value | Meaning |
|---|---|---|
cf-cache-status |
HIT |
Served from Cloudflare's edge cache |
cf-cache-status |
MISS |
Fetched from origin, now cached at edge |
cf-cache-status |
DYNAMIC |
Not cached — check your Cache Rules |
age |
3600 |
Content has been cached for 3600 seconds |
cache-control |
public, max-age=600 |
Ghost's caching headers are working |
Tip: The first request will always be a MISS. Run the command twice — the second request should return HIT with an age value above 0.
Method 2: Using browser DevTools
- Open Chrome and navigate to your blog
- Press
Ctrl + Shift + I(orCmd + Option + Ion Mac) to open DevTools - Go to the Network tab
- Refresh the page with
Ctrl + Shift + R(hard refresh) - Click the main document request (your blog URL)
- Check the Response Headers for
cf-cache-status,cache-control, andage
Method 3: Cloudflare Analytics dashboard
For ongoing monitoring, check Caching → Overview in your Cloudflare dashboard. This shows your cache hit ratio, bandwidth saved, and requests served from edge vs. origin. A well-configured Ghost blog should maintain a cache hit rate above 80%.
What common issues should you troubleshoot?
Even with correct configuration, several issues can prevent caching from working as expected:
| Problem | Cause | Solution |
|---|---|---|
cf-cache-status: DYNAMIC on all pages |
Cache Rule not matching or not deployed | Verify your rule expression and ensure it's active |
| Ghost admin panel not loading | Admin paths being cached | Add explicit bypass rule for /ghost/* paths |
| Preview links showing published version | Preview paths (/p/) being cached |
Exclude /p/ from caching rules |
| Stale content after publishing | No cache purge mechanism | Set up Cloudflare Worker with Ghost webhooks |
| Low cache hit rate (<50%) | Short TTLs or too many query string variations | Increase Edge TTL and enable query string sorting |
| Members/login not working | Cookies being stripped by cache | Bypass cache for authenticated paths or use Workers for cookie-aware caching |
What is the recommended caching configuration for Ghost blogs?
Based on my experience running Ghost blogs behind Cloudflare, here's the configuration I recommend for most sites:
| Layer | Setting | Value | Reason |
|---|---|---|---|
| Ghost config | frontend.maxAge |
600 (10 min) | Browser cache for returning visitors |
| Ghost config | contentAPI.maxAge |
60 (1 min) | API consumers get near-fresh data |
| Cloudflare Cache Rule | Edge Cache TTL | 7200 (2 hours) | Edge serves cached pages for 2 hours |
| Cloudflare Cache Rule | Bypass for /ghost/* |
Bypass | Admin panel always hits origin |
| Cloudflare Worker | Cache purge on publish | Automatic | Fresh content served immediately after publishing |
This setup delivers sub-100ms TTFB for most visitors while ensuring content updates appear within seconds of publishing.
Frequently asked questions
Does caching affect Ghost's member features or subscriptions?
Yes, it can. Ghost's member authentication relies on cookies. If you cache pages aggressively, logged-in members may see cached versions without their membership context. For sites using Ghost's membership features, bypass cache for authenticated requests or use a Cloudflare Worker that detects the ghost-members-ssr cookie and serves uncached responses to logged-in users.
How much does Cloudflare caching cost for a Ghost blog?
Cloudflare's Free plan includes caching, Cache Rules (10 rules), and their global CDN. For most Ghost blogs, this is sufficient. If you need Cloudflare Workers for automated cache purging, the Workers Free plan includes 100,000 requests per day. Paid plans start at $5/month for Cloudflare Workers Paid with 10 million requests per month.
Should I use Cloudflare APO for my Ghost blog?
No. Cloudflare's Automatic Platform Optimization (APO) is currently designed for WordPress only and requires the Cloudflare WordPress plugin. For Ghost blogs, use the Cache Rules approach described in this guide — it achieves similar results.
What Edge Cache TTL should I use?
For most Ghost blogs, 2 hours (7200 seconds) is a good balance between performance and freshness. If you have automated cache purging via Workers and webhooks, you can increase this to 24 hours for even better cache hit rates. Blogs that publish multiple times per day may want shorter TTLs of 30-60 minutes.
How do I clear the Cloudflare cache manually?
In the Cloudflare dashboard, go to Caching → Configuration and use Purge Everything for a full cache clear, or Custom Purge to clear specific URLs. Note that this only purges Cloudflare's edge cache — it won't affect content already cached in visitors' browsers.
Will caching break my Ghost blog's RSS feed or sitemap?
Ghost generates RSS feeds at /rss/ and sitemaps at /sitemap.xml. These will be cached along with other content. For RSS feeds, this is usually fine since feed readers check periodically. If you need sitemaps to update immediately (for search engine crawls after publishing), include them in your cache purge Worker logic.
Can I cache my Ghost blog if I'm using Ghost(Pro) hosting?
Ghost(Pro) includes built-in caching and a CDN through its hosting infrastructure. Adding Cloudflare in front of Ghost(Pro) can still provide benefits like DDoS protection, Web Application Firewall (WAF), and additional edge caching, but the performance gains will be smaller since Ghost(Pro) already handles caching.
What's the difference between "Cache Everything" in Page Rules and "Eligible for cache" in Cache Rules?
According to Cloudflare's migration guide, "Eligible for cache" in Cache Rules is the equivalent of "Cache Everything" in Page Rules. The key behavioral difference: Page Rules used first-match-wins logic, while Cache Rules are stackable — multiple matching rules combine and apply to the same request, with the last matching rule taking priority.