(Methods in this article current as of July 2025, and should apply towards any platform that handles cookies server-side)
Cloudflare has been a widely adopted and valuable service for many years, offering speed, security, and scalability benefits for nearly any website. Yet even today, many developers overlook or misunderstand how to properly configure static caching—especially when using a dynamic CMS like ExpressionEngine, and when cookies (like consent banners) are involved.
If you're only using Cloudflare as your DNS, you're just scratching the surface. While you'll see improved DNS reliability and asset performance (images, stylesheets, etc.), your full page load times can still be bottlenecked by unnecessary dynamic requests.
This post walks through the full setup to properly configure Cloudflare to serve your site from cache, reduce server load, and still respect ExpressionEngine’s admin and cookie behavior. (While this article is geared towards ExpressionEngine, these methods will work for any CMS that uses Apache or Nginx and and handles cookies server side)
Step 1: Configure Cache Headers on Your Web Server
Cloudflare relies on HTTP headers to determine whether a page is cacheable. If those headers are missing or improperly set, your site will default to "dynamic" mode, meaning Cloudflare will always fetch a fresh copy from your server.
This is a common mistake, especially among first-time Cloudflare users.
In my case, I’m using Plesk with Nginx. Within my domain’s settings, I configure a cache-control header to be sent with every URL:
Cache-Control: public, max-age=31536000

Step 2: Add Page Rules in Cloudflare
Now head to your Cloudflare dashboard and open the Rules section for your site.

Rule 1: Bypass Admin Pages
Create a page rule that bypasses caching for ExpressionEngine’s control panel. This is typically any URL containing /admin.php (or whatever your CP trigger is).
Rule example:
→ example.com/admin.php*
→ Cache Level: Bypass
This ensures Cloudflare won’t interfere with login states or admin page behavior.
Rule 2: Cache Everything Else
Next, create a page rule that caches your entire site at the edge:
Rule example:
→example.com/*
→ Cache Level: Cache Everything
→ Edge Cache TTL: [choose based on your update frequency]
Now, your public-facing pages will be fully cached by Cloudflare, reducing the number of requests hitting your server.
Step 3: Test the Cache Status

Reload one of your public pages while inspecting the cf-cache-status header. Open your browser’s developer tools, go to the Network tab, and reload your site. Look for Cloudflare-specific headers like cf-cache-status. You should now see "MISS" or "HIT" depending on whether the resource is cached:
- MISS means Cloudflare looked for the cached version but didn’t find it (yet).
- HIT means your page was served directly from Cloudflare’s cache (ideal!).
- DYNAMIC – Cloudflare deliberately bypassed the cache, often because of cookies, query strings, or cache rules that indicate the content is dynamic and should not be cached.
Refresh twice to confirm: the first load should be "MISS", the second should be "HIT". Note: it is useful to use a secondary browser, and/or use Private/Incognito mode, as your primary browser may locally cache resources that prevent you from seeing the proper cf-cache-status.
Step 4: Account for Cookie-Dependent Behavior (Like Consent Modules)
Many websites—including mine—use a consent module that depends on cookies to store user preferences. In ExpressionEngine, these cookies typically start with exp_ and are managed by first-party add-ons, and the cookies are handled on the server side rather than with javascript.
By default, Cloudflare may cache pages even when these cookies are present, which can break consent tracking. To fix this:
1) In the Cloudflare dashboard, go to the Caching section and locate the area for Cache Rules (this may vary by plan level).
2) Create a new rule that bypasses caching if a cookie name starts with exp_

3) Save your settings.
4) Once done, test your site in private/incognito mode across multiple browsers to confirm your consent banner appears and properly stores user choices.
Conclusion
With these steps in place, you're now leveraging the full speed and power of Cloudflare's edge caching, while avoiding common pitfalls like caching admin URLs or breaking consent behavior.
- ✅ Your pages are served statically and quickly.
- ✅ Admin interfaces remain dynamic and functional.
- ✅ Cookie-based features like consent modules continue to behave correctly.
This hybrid setup is ideal for ExpressionEngine users—and ensures your audience enjoys lightning-fast load times without sacrificing control or compliance.