Skip to main content

Rule examples: WordPress

This page documents the exact WordPress ruleset that Paradarum ships as a one-click preset: which paths get cached, for how long, which cookies bypass the cache, and the recommended general settings. You can build it by hand from the tables below, or apply the whole bundle in a single click from the CMS Presets Quick Setup card.

:::tip Apply it in one click Instead of creating these rules manually, open the Quick Setup card on the property's General settings page, choose WordPress, and click Apply Preset. Paradarum creates each rule below as an individual, editable cache rule and then applies the recommended general settings. See CMS Presets for the full flow. :::

:::info Keep the cache fresh automatically These rules control what is cached. To automatically purge the cache when you publish or edit content, install the Paradarum CDN Purge plugin for WordPress. :::

Cache rules

WordPress mixes static assets (safe to cache for a long time) with dynamic, per-user pages (the admin area, login, and authenticated sessions). The preset caches assets aggressively, bypasses the admin and login surfaces entirely, gives the REST API a tiny TTL, and falls back to a short page cache for everything else.

The patterns use nginx-style location matching: ~* is a case-insensitive regex (matched against the request URI), ^~ is a prefix match, and the bare / is the catch-all fallback that runs last.

OrderPath / patternMatchTTL (seconds)Meaning
1~* \.(jpg|jpeg|png|gif|ico|svg|css|js|woff|woff2|ttf|eot)$Regex2592000Static assets cached 30 days
2^~ /wp-admin/Starts with0Admin area — never cached
3^~ /wp-login.phpStarts with0Login — never cached
4^~ /wp-json/Starts with10REST API — 10s micro-cache
10/Catch-all1800Pages cached 30 minutes

:::info TTL of 0 means bypass A TTL of 0 seconds tells the edge never to cache that location. That is why /wp-admin/ and /wp-login.php are set to 0 — those responses are always served fresh. The catch-all / rule is given order 10 so it always runs last, after the more specific rules. :::

Create the cache rules via the API

Each preset rule maps to a POST /api/Property/{propertyId}/rules/cache call against https://api.paradarum.com. The examples below use a property ID of 123 and authenticate with an account API key sent in the X-API-Key header. A panel JWT via Authorization: Bearer <JWT> works too.

# 1. Static assets — 30 days
curl -X POST \
-H "X-API-Key: pdm_YOUR_KEY" \
-H "Content-Type: application/json" \
https://api.paradarum.com/api/Property/123/rules/cache \
-d '{
"name": "WP: Cache Static Assets (30d)",
"pattern": "\\.(jpg|jpeg|png|gif|ico|svg|css|js|woff|woff2|ttf|eot)$",
"matchType": 4,
"ttlSeconds": 2592000,
"description": "Applied from WordPress preset",
"order": 1,
"isEnabled": true
}'
# 2. wp-admin — never cache
curl -X POST \
-H "X-API-Key: pdm_YOUR_KEY" \
-H "Content-Type: application/json" \
https://api.paradarum.com/api/Property/123/rules/cache \
-d '{
"name": "WP: Bypass wp-admin",
"pattern": "/wp-admin/",
"matchType": 2,
"ttlSeconds": 0,
"description": "Applied from WordPress preset",
"order": 2,
"isEnabled": true
}'
# 3. wp-login.php — never cache
curl -X POST \
-H "X-API-Key: pdm_YOUR_KEY" \
-H "Content-Type: application/json" \
https://api.paradarum.com/api/Property/123/rules/cache \
-d '{
"name": "WP: Bypass wp-login",
"pattern": "/wp-login.php",
"matchType": 2,
"ttlSeconds": 0,
"description": "Applied from WordPress preset",
"order": 3,
"isEnabled": true
}'
# 4. wp-json REST API — 10s micro-cache
curl -X POST \
-H "X-API-Key: pdm_YOUR_KEY" \
-H "Content-Type: application/json" \
https://api.paradarum.com/api/Property/123/rules/cache \
-d '{
"name": "WP: Cache REST API (10s)",
"pattern": "/wp-json/",
"matchType": 2,
"ttlSeconds": 10,
"description": "Applied from WordPress preset",
"order": 4,
"isEnabled": true
}'
# 10. Catch-all pages — 30 minutes
curl -X POST \
-H "X-API-Key: pdm_YOUR_KEY" \
-H "Content-Type: application/json" \
https://api.paradarum.com/api/Property/123/rules/cache \
-d '{
"name": "WP: Cache Pages (30min)",
"pattern": "/",
"ttlSeconds": 1800,
"description": "Applied from WordPress preset",
"order": 10,
"isEnabled": true
}'

The matchType integers are Equals=0, Contains=1, StartsWith=2, EndsWith=3, Regex=4. The catch-all / rule omits matchType because it is a bare fallback pattern. See match operators for the full mapping.

:::note Changes propagate when the edge polls Creating or editing a rule does not push to the OpenResty edge synchronously — the edge polls configuration, so changes go live within a short interval rather than instantly. :::

Bypass cookies

A page cache is only safe if logged-in users are never served another visitor's cached page. The WordPress preset bypasses the cache whenever any of these cookie name prefixes is present on the request:

Cookie prefixSet when
wordpress_logged_in_A user is authenticated to the dashboard
wp-settings-A logged-in user has saved admin UI preferences
comment_author_A visitor has left a comment (their details are remembered)
wp-postpass_A visitor has entered a password-protected post password

These bypass cookies are expressed in a rule's Location Features as a bypass_cookies array inside featuresJson. You can attach them to the catch-all page rule so any authenticated or commenting visitor always gets a fresh response:

{
"name": "WP: Cache Pages (30min)",
"pattern": "/",
"ttlSeconds": 1800,
"order": 10,
"isEnabled": true,
"featuresJson": "{\"bypass_cookies\":[\"wordpress_logged_in_\",\"wp-settings-\",\"comment_author_\",\"wp-postpass_\"]}"
}

:::warning Bypass cookies are not auto-applied by Quick Setup The Quick Setup apply action creates the cache rules and applies the general settings, but it does not automatically attach the preset's bypass-cookie list. After applying the WordPress preset, open the catch-all page rule (and any other page-serving rule) and add the four cookie prefixes above under Location Features → Cache Bypass Cookies, or include them in featuresJson as shown. Without this, logged-in users risk being served cached pages. :::

The WordPress preset also applies a set of property-wide general settings covering security headers, tracking-parameter stripping, browser caching, and always-online behavior. This is the exact bundle from the preset:

{
"hsts": { "enabled": true, "max_age": 31536000, "include_subdomains": true, "preload": true },
"clickjacking_protection": true,
"mime_sniffing_protection": true,
"query_string": {
"mode": "only",
"values": ["utm_source", "utm_medium", "utm_campaign", "fbclid", "gclid", "_ga", "_gid"]
},
"always_online": { "enabled": true, "codes": ["error", "500", "502", "503", "504"] },
"browser_caching": { "mode": "override", "ttl": 3600 }
}
SettingValueWhat it does
HSTSEnabled, max_age 31536000 (1 year), include_subdomains, preloadForces HTTPS for a year, including subdomains; opts into the preload list
Clickjacking protectiontrueSends a frame-protection security header
MIME-sniffing protectiontrueSends an X-Content-Type-Options: nosniff style header
Query stringmode: only with a values listStrips tracking params from the cache key (see below)
Always OnlineEnabled for error, 500, 502, 503, 504Serves a cached copy when the origin returns those errors
Browser cachingmode: override, ttl 3600Overrides downstream browser cache lifetime to 1 hour

Query-string handling: strip tracking parameters

The query_string values list (with mode: only) removes common marketing and analytics parameters (utm_source, utm_medium, utm_campaign, fbclid, gclid, _ga, _gid) from the cache key. Without this, ?utm_source=newsletter and ?utm_source=twitter would be cached as two separate copies of the same page, fragmenting your hit rate. Stripping them means one cached page serves every campaign variant.

tip

Add your own tracking or session parameters to the values list if your campaigns use them — anything that does not change the rendered HTML but does change the URL is a good candidate.

Where to go next