How Core dna caches pages, what makes a render fast, how code reaches a site and what stays behind, the go-live checklist, and running a site once it is live. For developers, leads and site operators who already build pages in a theme repository.
L2–L3
Unit 06 · Running a site after launch
Uptime, failover and maintenance
Running a site after launchPage 32 of 34Updated
What a static failover page is for, what it must contain to be any use, a real one from a production site, the build step that stops it going stale, and how to handle planned maintenance without a release.
Who this is for. The developer responsible for a site that cannot afford to show an error page during an outage or a traffic spike. Afterwards you can say what a failover can and cannot do, build one that stays current with every release, and put up a maintenance notice without deploying.
A site can be unavailable for reasons outside the theme: a platform incident, a spike of traffic beyond what it was sized for, a provider it depends on failing. A static failover is a plain HTML page, kept ready, that visitors see instead of an error while that lasts. It cannot sell, sign anyone in or search, but it can tell visitors what is happening and send them somewhere useful, which is the difference between an outage and a lost customer.
What a failover serves, and when
A failover is served from in front of the platform, not by it, because that layer is the only one still there when a site is down. Whether a failover is used for a site, at what point and for which paths, is arranged with Core dna, and so is how the page reaches the layer that serves it.
A real failover
A ticketing site whose presales bring sudden peaks keeps its failover in the theme repository, in a folder of its own:
HTML
failover/
index.html the page: a high-demand notice, what to do now, and the current tours as plain links
top-bar.html the site's header as static HTML
side-panel.html
assets/ the logos and images the page uses
Its message is specific: you are visiting during a high-demand period, please wait, and if you already have a presale code and know the official ticketing agency, go there directly. That last line is the useful part: it sends visitors to the place where they can still complete their task.
It also shows how a failover goes stale. It loads the site's built stylesheet with the version string written into the file by hand, and lists the current tours as they were when it was last edited. A release that renames classes leaves it unstyled, and a tour list three months old sends visitors to finished events.
What it must contain
Nothing that needs the platform: no search, no sign-in, no form that posts to the site, no request to the site's API. Styles and images inline, or served by the same layer as the page.
What is happening, in one sentence, and when to try again.
What visitors can do instead: a phone number, an email address, the partner or agency site where the task can still be completed.
The brand, so visitors know they are in the right place.
noindex, so a search engine that meets the page never keeps it as the site's home page.
The build step that keeps it current
A failover is only as good as its last update, so make updating it part of every release rather than a task someone remembers. A build step can produce it from the data the site shows, with the current asset version and the current links. This one reads the children of a listing page through the REST API, with an integration's access token:
JavaScriptscripts/build-failover.mjs
// scripts/build-failover.mjs: run by the release build, writes failover/index.html
import { readFileSync, writeFileSync } from 'node:fs';
import { execSync } from 'node:child_process';
const version = execSync('git rev-parse --short=7 HEAD').toString().trim();
const query = new URLSearchParams({
'parent.id': process.env.TOURS_PAGE_ID,
properties: '{name,fullPath}'
});
const res = await fetch(`${process.env.SITE_URL}/cdna-api/pages/pages?${query}`, {
headers: { Authorization: `Bearer ${process.env.CDNA_TOKEN}`, Accept: 'application/json' }
});
if (!res.ok) throw new Error(`Page list failed: ${res.status}`);
const pages = (await res.json()).data;
const escape = s => s.replace(/[&<>"]/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c]));
const links = pages.map(p => `<li><a href="${p.fullPath}">${escape(p.name)}</a></li>`).join('\n');
const page = readFileSync('failover/template.html', 'utf8')
.replace('%%VERSION%%', version)
.replace('%%LINKS%%', links);
writeFileSync('failover/index.html', page);
The list answers {"result": "success", "totalCount": …, "data": [{"name": …, "fullPath": …}]}: the pages are the data array itself. The template file keeps the text and the layout; the script fills in what changes, and the build fails loudly rather than writing an empty list when the request fails.
Planned maintenance
Platform upgrades are scheduled by Core dna; ask for the window and check the site straight after, with the smoke checks from CI (a minimal useful pipeline).
Your own heavy work, a full reindex, a large import, a bulk content change, belongs out of hours: each competes with visitors and with the platform's background queue (how long a reindex takes).
A notice to visitors during a planned window is a banner driven by a site data value, so an administrator can put it up and take it down without a release:
{% set notice = _siteData.get('maintenanceNotice') %}
{% if notice %}
<div class="site-notice" role="status">{{ notice|e }}</div>
{% endif %}
Pages already in the page cache keep the state they were stored with until they are cleared or expire, so check a cached page signed out after switching the notice on, and clear the cache if it does not show.