How the Cloudflare module is built - edge header plugins, purge queue, health runner, admin surface and cron
Module identity
OCMLabs_Cloudflare, namespace OCMLabs\Cloudflare, Composer package ocmlabs/module-cloudflare, licence OSL-3.0. PHP 8.1 or later with declare(strict_types=1) on every file. Depends on magento/framework 103.0.x (Magento 2.4.4 and later), the page cache, store, config, catalog, CMS, URL rewrite, message queue and cron modules, and Guzzle 7. All Cloudflare calls go through one API client; all configuration reads go through one Config model.
Edge headers
Three frontend plugins decide what Cloudflare may cache:
- Kernel marker (
beforeplugin onMagento\Framework\App\PageCache\Kernel::process). The built-in full page cache strips headers and saves the remaininggetHeaders()->toArray()with the page. The plugin runs first and adds two markers, an internal edge TTL header (X-OCMLabs-Edge-TTL) andCache-Tag, so they are stored with the page and survive on cache hits. - Result marker (
afterplugin onResultInterface::renderResult). The Varnish-mode equivalent: in Varnish mode the kernel is not involved, so the markers are added when the result renders. - Response send (plugin on
Magento\Framework\App\Response\Http::sendResponse). The header policy runs last. In built-in mode it turns the marker intoCache-Control: public, max-age=0, s-maxage=<ttl>plusCDN-Cache-Control, strips the session cookies (Laminas and nativeheader()cookies both), re-checks the bypass matcher, and sendsprivate, no-storeon everything else, including responses that setX-Magento-Vary(unless vary handling iscache_key, where a re-asserted default value is allowed). In Varnish mode it leaves headers and cookies to Varnish and only keeps the marker andCache-Tagfor the VCL.
With the module disabled, or edge caching off, the policy sends private, no-store on every storefront response.
Purge pipeline
- Observers.
clean_cache_by_tagsandclean_cache_after_reindexfeed the tag observer;adminhtml_cache_flush_allandadminhtml_cache_flush_systemfeed the flush observer. A plugin onTypeListInterfacecatches a refresh of thefull_pagecache type, which does not fire an event. All observers are global, becausebin/magento cache:cleandispatches the adminhtml events outside the adminhtml area. - Dispatcher. Normalises the request (tags lowercased, store and website tags dropped), resolves the websites and zones involved, and either publishes to the queue (async) or runs the strategy immediately (sync, CLI and dashboard quick purge).
- Queue. Topic
ocmlabs.cloudflare.purgeon thedbconnection, consumerocmlabsCloudflarePurgeusing Magento’sBatchConsumerwith a custom merger that folds every waiting message into one merged message grouped by zone. - Consumer. Per group, in a try/catch so one zone’s failure does not stop another: chunk to 100 items, take one rate limiter token per chunk, send, log. On an empty bucket or a
429it blocks the bucket forRetry-After, re-queues the remainder and returns. More than 20 waiting messages for a zone collapse into a purge-everything. - Strategies.
tagsends raw tags;urlresolves tags to URLs through the URL finder (store-scoped, configurable parents, paginated categories, 500 per tag, 5000 aggregate);prefixandeverythingmap directly to the Cloudflare endpoints. - Rate limiter. A token bucket per Cloudflare account stored in the module cache type, sized by plan: Free 5 per minute (burst 25), Pro 5 per second (25), Business 10 per second (50), Enterprise 50 per second (500).
API client
One Guzzle-based client for https://api.cloudflare.com/client/v4/ with retries on transient errors, 100-item chunking, typed exceptions (authentication, permission, rate limit, API error) and token redaction in every logged or stored message. Debug logging writes request and response summaries to var/log/ocmlabs_cloudflare.log.
Cache rules are managed through the Rulesets API (http_request_cache_settings phase): the module reads the zone’s entrypoint ruleset, computes a diff against the rules it would write for the website, and replaces only the [OCMLabs] ... (<website code>) rules, keeping merchant rules in their positions. Analytics use the GraphQL Analytics API with httpRequests1mGroups, httpRequests1dGroups and httpRequestsAdaptiveGroups datasets.
Health runner
Twenty-five checks implement one interface (code, title, group, run) and are registered in di.xml as an ordered pool, so a custom check can be added with a di.xml entry. The runner executes them for a website, catches exceptions per check so one API failure does not blank the page, and stores the results in the module cache type with a timestamp. Live probes go through a prober with an SSRF guard that only fetches URLs resolving to the website’s configured hosts, and require an HTTP 200.
Real IP
A plugin on Magento\Framework\HTTP\PhpEnvironment\RemoteAddress. It returns CF-Connecting-IP only when the raw REMOTE_ADDR is inside Cloudflare’s ranges (IPv4 and IPv6, including IPv4-mapped IPv6). Ranges come from the module cache type, refreshed daily, with a bundled copy as the fallback.
Database
One table, ocmlabs_cloudflare_purge_log: zone ID, website ID, mode, item count, items (JSON, capped at 64 KB), trigger, status (success, failed, queued), Cloudflare request ID, error, duration in milliseconds, created at. Indexed on created_at and status.
Cache type
ocmlabs_cloudflare (“OCM Labs Cloudflare” under System > Cache Management) holds zone details, analytics responses, health results, the rate limiter buckets and the Cloudflare IP ranges. Flushing it is safe; everything is refetched.
Cron jobs
| Job | Schedule | Purpose |
|---|---|---|
ocmlabs_ | 15 minutes past every hour | Run the health checks for every website with a zone |
ocmlabs_ | every 15 minutes | Warm the analytics cache for each website’s default range |
ocmlabs_ | 04:30 daily | Refresh Cloudflare’s published IP ranges |
ocmlabs_ | 03:00 daily | Delete purge log rows older than 30 days |
All module cron work is skipped while Enable Cloudflare Integration is off.
Admin surface
Route frontName ocmlabs_cloudflare, menu System > Cloudflare with Dashboard and Purge Log. The dashboard is one page with Overview, Analytics and Health tabs backed by AJAX controllers; the purge log is a UI component grid with a detail view. Config section ocmlabs_cloudflare with Test Connection and Detect Zone buttons. ACL: OCMLabs_Cloudflare::dashboard with children ::purge, ::settings_write and ::purge_log, plus ::config under Stores > Configuration. The admin footer shows the module version with links to the docs, the issue tracker and the OCM Labs catalogue; the module makes no other outbound requests than Cloudflare’s API and your own storefront.
Console commands
Six commands under ocmlabs:cloudflare: (purge, status, dev-mode, health, rules:apply, vcl:export). The command list is built on every bin/magento call, so the heavy services are injected as proxies. See the CLI Reference.
Tests
409 PHPUnit unit tests run against a plain Magento checkout in CI (PHP 8.1 and 8.2 lint with phpcs on the Magento coding standard, unit tests on Magento 2.4.8).