The front cache & Drupal's page cache
Two layers serve whole pages before Drupal does any real work: the Nginx front cache (BOA calls it Speed Booster) and Drupal's own page cache, which on BOA lives in the fast Redis/Valkey object cache. They're tuned to work together, and the defaults are right for almost every site — but both have a dial, and there's a right and a wrong way to make a page dynamic.
Speed Booster: the Nginx micro-cache
Speed Booster runs in micro-caching mode: a page may be served straight from Nginx for a short window — 10 seconds by default — without PHP or Drupal running at all. Ten seconds sounds tiny, but on a busy page it means one page build serves everyone who arrives in that window, which flattens traffic spikes beautifully while keeping content essentially fresh.
It's smarter than a blunt page cache, and worth knowing exactly how:
- Logged-in users are cached too — each in their own bin. The cache key includes the visitor's session, so logged-in visitors get a private micro-cache (same short window) that can never leak between users, and a separate device class (desktop, tablet, smartphone) keeps mobile themes safe to serve.
- It steps aside when it must. Any form submission (POST) switches the
cache off for that visitor for 15 seconds, and requests to
/user*,/admin*, cart and checkout paths always bypass it — so editing, logging in and shopping never see a stale page. - Crawlers get much longer. Known robots and search-engine spiders are forced to accept a much longer cache window than human visitors, so bot swarms never stampede your site.
- You can raise the anonymous window.
speed_booster_anon_cache_ttlsets the anonymous-visitor TTL in seconds. Values of 10 or below are ignored — 10 is the floor. - On a
.dev.preview URL the window drops to 1 second, so development work is effectively uncached at this layer too.
; sites/<your-domain>/modules/boa_site_control.ini
speed_booster_anon_cache_ttl = 30
If you raise the TTL meaningfully, consider enabling the Purge and Expire modules on your site: they selectively purge affected front-cache entries when a node or comment changes, so a longer TTL doesn't mean serving stale content until it expires. And if you're on Drupal 6 or 7, read the AdvAgg section below — a raised TTL is exactly what turns a routine cache clear into temporarily broken styling.
Drupal's page cache stays on — here's why
BOA keeps Drupal's own full-page cache enabled, and stores it in Redis/Valkey. The two layers cover for each other: the front cache absorbs the repeat traffic within its few-second window, and the page cache makes the request that misses the front cache (the first one after each window expires) nearly free as well, because the page comes ready-made from memory.
That's why disable_drupal_page_cache = TRUE is almost always the wrong move.
With the front cache holding pages for only seconds, turning the page cache off
means Drupal rebuilds pages from scratch all day — your site gets noticeably,
randomly slower for every anonymous visitor, even if you raise the front-cache
TTL. (Legacy note: if the Boost module complains that the page cache is on,
let it complain — BOA's default is deliberate.)
| Setting | What it does | Default |
|---|---|---|
speed_booster_anon_cache_ttl |
Seconds an anonymous visitor's page may be served from the Nginx front cache. Values of 10 or below are ignored. | 10 |
disable_drupal_page_cache |
TRUE switches off Drupal's own full-page cache. Read the section above before even thinking about it. |
FALSE |
Both work in either control file — see Platform and site INI settings for the mechanics.
When a cache clear breaks your styling: AdvAgg
This one shows up almost exclusively on Drupal 6/7 sites that raised the front-cache TTL: someone clears the site's caches, and for a while visitors get pages with broken or missing CSS and JavaScript — then it heals on its own.
The mechanism: Drupal 6/7's standard aggregation deletes its old aggregate CSS/JS files when caches are cleared, but pages already sitting in the front cache still reference those now-deleted files, so every visitor served from the cache for the rest of the window gets a page whose stylesheet links go nowhere. With the default 10-second window nobody ever notices. With a raised TTL, the breakage lasts as long as your window has left to run.
The remedy is the AdvAgg (Advanced CSS/JS Aggregation) module, bundled
with every BOA-built Drupal 6 and 7 platform — it lives in the platform's
shared o_contrib/o_contrib_seven module directories, and a copy you
upload to sites/all/modules/advagg is respected as an override (see
Modules BOA manages for how the bundled extras
work). AdvAgg is built around exactly this problem: it generates aggregates
with stable names and leaves the existing aggregate files in place on a flush
instead of purging them, so pages cached before the clear keep rendering
correctly after it.
Enabling the module is all you do — BOA notices. The nightly maintenance pass
detects AdvAgg enabled on your site and sets
advagg_auto_configuration = TRUE in your site's control file, which applies
a tuned, core-version-specific AdvAgg profile (bundler, compression, gzip,
async generation) at the settings level. If you later disable the module, the
same pass flips the setting back to FALSE — it always mirrors the module's
actual status, so there is nothing to maintain. (On .dev. preview URLs the
tuned profile is not applied, in line with the rest of the no-cache dev view.
And on Drupal 8 and newer none of this machinery applies — BOA doesn't bundle
or auto-configure AdvAgg there; if you want it, you add and configure it
yourself like any contrib module.)
Making one URL truly dynamic (the right way)
First, two cases this section is not for: a one-off uncached look at a page
(append ?nocache=1 to the URL instead — that single request skips both
page-level caches), and development (use the
.dev. preview URL).
Sometimes one page genuinely must be rebuilt for every anonymous visitor — a
per-visitor result with no cookie or form involved. Don't disable caching
site-wide for that. Add a targeted exception to your site's
local.settings.php instead. On Drupal 6/7:
if (preg_match("/^\/(?:live-results|stock-ticker)/", $_SERVER['REQUEST_URI'])) {
header('X-Accel-Expires: 1'); // skip the Nginx front cache for this URL
$conf['cache'] = 0; // skip Drupal's page cache on the fly
}
The first line exempts the URL from Speed Booster; the second keeps Drupal from
serving it out of the page cache. On Drupal 8+ the front-cache line is the
same, and the page-cache line becomes the config override
$config['system.performance']['cache.page.max_age'] = 0;. Everything else on
the site stays fully cached.
Related
- The Redis/Valkey object cache — the layer the page cache is stored in, and everything about cache bins.
- PHP opcache & APCu — why deployed changes take about a minute to appear.
- Something looks broken — when a stale page means a cache needs clearing.