Headless WordPress

Hosting and Deploying a Headless WordPress Stack

Two applications, two hosts and two deploy pipelines. How to arrange them, keep the CMS off the public domain, and handle builds that need WordPress up.

By 6 min read
WordPress admin connected by an API to a separately hosted frontend

The architecture conversation about headless WordPress usually stops at the API. The operational conversation — where each piece lives, how it deploys, what happens when one is down — is where the ongoing cost actually sits.

Here's how I arrange it and what to decide up front.

Two applications, two sets of needs

WordPress needs PHP, MySQL, a filesystem for uploads, and reliable scheduled tasks. It's read-and-write, it's used by a handful of editors, and it doesn't need to be fast for the public.

The frontend needs a Node runtime or a static file host, an edge network, and to be fast for everyone. It's read-mostly and it takes all the public traffic.

Those are different products. Trying to run both on one host usually means compromising on one of them, and the compromise is normally the frontend.

Where WordPress should live

  • On its own hostname — cms.example.com or similar — not on the public site's domain.
  • Behind HTTP authentication or an IP allowlist for wp-admin and wp-login.php, if the editors work from predictable places.
  • Noindexed, so the CMS copy of your content never appears in search results competing with the real site.
  • On hosting suited to WordPress: PHP 8.x with OPcache, an object cache available, and real cron rather than wp-cron.
  • With its own backups, since it holds all the content.
  • Sized for editors and build traffic, not for public traffic. This is usually much less server than the equivalent traditional site would need.

Where the frontend should live

A platform that handles static hosting, edge distribution, build pipelines and preview deployments is the path of least resistance, and the tooling for it is mature.

The key capabilities to look for: builds triggered by a Git push, on-demand revalidation so editors' changes appear without a full rebuild, environment variable management per environment, and preview deployments per branch.

Self-hosting the frontend is entirely possible and means running a Node process, a reverse proxy and your own CDN configuration. It's more control and more operational work.

Builds that depend on WordPress

A statically generated frontend fetches all its content at build time, which makes every deploy dependent on WordPress being up and responsive.

This is the operational wrinkle people don't anticipate. WordPress being slow makes builds slow; WordPress being down makes deploys impossible, including the deploy that would fix something else.

  • Give the build generous timeouts and retries on its API calls.
  • Cache API responses during the build, so a rebuild of a large site doesn't refetch everything.
  • Fail the build loudly on a fetch error rather than silently publishing a site with missing pages.
  • Keep the last successful build deployed if a new one fails, which most platforms do by default.
  • For very large sites, fetch incrementally rather than rebuilding everything, or build times grow with your content.

Revalidation over rebuilding

Rebuilding the whole site when an editor fixes a typo is slow and wasteful. On-demand revalidation regenerates only the affected pages.

The mechanism: WordPress calls a webhook on the frontend when a post is saved; the frontend regenerates that page plus the listings it appears on.

Protect that endpoint with a secret, revalidate only the affected paths rather than everything, and keep a time-based fallback so a missed webhook doesn't leave a page stale indefinitely.

Also keep a manual full rebuild available. You'll need it after a theme change, a bulk content import, or any time the incremental state gets confused.

Environments

You need at least two of each, and they need to point at each other correctly.

  • Staging WordPress and staging frontend, with the frontend pointing at staging WordPress. A staging frontend fetching production content is a trap that looks like it works.
  • Production WordPress and production frontend.
  • Branch preview deployments of the frontend, pointing at staging WordPress.
  • Environment variables per environment: the API URL, the preview secret, the revalidation secret, any credentials.
  • Make the environment obvious in both — a banner on the frontend, a coloured admin bar in WordPress. Editing production thinking it's staging is a recurring accident.

Secrets across two systems

  • The preview token secret and the revalidation secret are shared between WordPress and the frontend. Store them in both systems' environment configuration, never in either repository.
  • The application password the frontend uses to fetch drafts should be on a dedicated WordPress account with the minimum capability.
  • Rotate both sides together. A secret rotated on one side silently breaks preview or revalidation, which nobody notices until an editor complains.
  • Document which secret is used for what, because there will be three or four and they are indistinguishable in a settings screen.

Monitoring both halves

  • Uptime monitoring on the public frontend, which is what visitors see.
  • Separate uptime monitoring on WordPress, because it can be down without the static frontend showing anything wrong — and you need to know before someone tries to publish.
  • Build failure alerts, so a failed deploy doesn't sit unnoticed.
  • Revalidation failure alerts, or editors will simply report that publishing doesn't work.
  • Watch for the failure mode where WordPress is down and the site looks fine. It's a genuine resilience benefit, and it means nothing tells you until someone tries to edit.

The cost picture

Two hosts instead of one, though the WordPress host can be smaller than it would otherwise need to be since it isn't serving public traffic.

A frontend platform, which often has a usable free tier for small sites and gets meaningful at scale.

More engineering time: two pipelines, two sets of environment configuration, two things to monitor and debug.

Against that: a faster site, a smaller public attack surface, and a frontend that keeps serving through a WordPress outage. Whether that trade is worth it depends on the project — but it should be a deliberate trade rather than a discovery made in month three.

Frequently asked questions

Where should WordPress live in a headless setup?

On its own hostname, separate from the public site's domain, noindexed, and locked down — HTTP authentication or an IP allowlist on wp-admin where practical. It only serves editors and builds, so it needs far less capacity than the equivalent traditional site.

What happens to a headless site if WordPress goes down?

A statically generated frontend keeps serving normally, which is a genuine resilience benefit. What stops is publishing, previews and any deploy that needs to fetch content. Monitor WordPress separately, because the public site looking fine tells you nothing about whether the CMS is up.

Do I need to rebuild the whole site every time content changes?

No, and you shouldn't. Use on-demand revalidation: WordPress calls a webhook when a post is saved, and the frontend regenerates just that page and the listings it appears on. Keep a time-based fallback for missed webhooks and a manual full rebuild for when things get out of step.

Is headless WordPress more expensive to host?

Two hosts instead of one, though the WordPress side can be smaller since it isn't serving public traffic. The bigger cost is engineering time — two pipelines, two sets of environment configuration, two things to monitor. The infrastructure bill is rarely the deciding factor.

Should my staging frontend point at production WordPress?

No, and it's a trap that looks like it works. Staging frontend points at staging WordPress; production points at production. Otherwise you can't test content changes safely, and a revalidation webhook from production will hit an environment you didn't intend.

Topics

  • headless WordPress hosting
  • headless deployment
  • Next.js hosting
  • decoupled WordPress