A managed edge cache in front of a custom domain

Embed
Preview of the card
<a href="https://forumulate.com/guides/managed-edge"><img src="https://forumulate.com/guides/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/36aa4df0-1e95-4cef-8ae9-795169441345/pages/d001f333-87b2-407c-bd44-bf3b5b938498/social-card.svg?v=3e7ae33eec8b" alt="A managed edge cache in front of a custom domain" width="600" height="315"></a>

A custom domain that points straight at us has nothing in front of it. That is fine for most sites. When you want a CDN — readers far from our origin, a launch — put one in front, configured to the same cache rules our own zone runs, so nothing personal is ever served from it.

The rules

  1. Cache only GET/HEAD requests with no Cookie and no Authorization header.

  2. Never a request with share, draft or preview in the query.

  3. Never a router request (RSC, Next-Router-State-Tree, Next-Router-Prefetch).

  4. Never /api/*.

  5. The origin decides the TTL (s-maxage=10, also as CDN-Cache-Control); never store private/no-store; set no edge TTL of your own.

  6. Forward the original Host header.

Breaking 1–3 serves one reader's page (a draft, a signed-in view, a gated page) to everyone after them. Breaking 5 makes a published edit or a deletion wait for your TTL instead of ten seconds.

Choose a provider

PUT /api/orgs/{org}/spaces/{space}/domains/{domainId}/edge
{ "mode": "managed", "provider": "fastly", "settings": { "serviceId": "SU1Z0..." } }

Provider

What we automate

What you do

cloudflare-saas (Cloudflare for SaaS)

the custom hostname (its verification records are returned) and the cache rule, added beside your other rules

the token, the fallback origin, the DNS record

fastly

clone the active version, add the domain and two VCL snippets, activate

the token and service, the backend, the DNS record

bunny

add the hostname to the pull zone

the key and pull zone, origin settings, the bypass edge rules, the DNS record

cloudfront

— (we never hold AWS credentials)

distribution, cache policy, the viewer-request function, a purge Lambda

custom

—

the six rules in your CDN, a purge endpoint

GET …/edge answers the plan: DNS records, every step (marked automated or not) and the exact configuration in the provider's own language — the Cloudflare ruleset expression, the Fastly VCL, the Bunny settings, the CloudFront cache policy and function. POST …/edge/provision runs the automated steps with the credentials you saved under Integrations → CDN (Fastly, Bunny, a signed webhook) or Integrations → Cloudflare, and answers each step's result.

Purge on publish

Choosing a provider links the domain into that provider's purge credentials, so a publish clears the page at the edge in seconds. CloudFront and other CDNs are purged through the signed webhook provider: we POST the URLs, your function invalidates them.

Check it

POST …/edge/check requests the address from outside as an anonymous reader (twice), with a session cookie, with a preview link, and as a router request. It fails if any personal request was answered from the cache or the edge held a copy past our TTL, and warns when anonymous pages are not cached yet or no purge credentials cover the address. Run it after every change to your CDN.

In the API

Every operation below is also reachable from the other surfaces without a dedicated command. forumulate api <Operation> calls it from the CLI, the JavaScript SDK has a typed method for each one (the last column names it; the Python and Go SDKs are generated from the same spec), and an agent reaches the organization-scoped ones through the MCP agent server — its api_* family tools, or call_api. Where a CLI command or a hand-made MCP tool exists too, the last column names it. Operation names link to the API reference.

Managed Edge

Operation

Request

What it does

Shortcuts

ManagedEdge_get

GET /orgs/{orgId}/spaces/{spaceId}/domains/{domainId}/edge

The managed edge in front of a custom domain

client.managedEdge.get()

ManagedEdge_set

PUT /orgs/{orgId}/spaces/{spaceId}/domains/{domainId}/edge

Choose the managed edge for a custom domain

client.managedEdge.set()

ManagedEdge_patch

PATCH /orgs/{orgId}/spaces/{spaceId}/domains/{domainId}/edge

Change part of the managed edge for a custom domain

client.managedEdge.patch()

ManagedEdge_provision

POST /orgs/{orgId}/spaces/{spaceId}/domains/{domainId}/edge/provision

Run the automated setup steps

client.managedEdge.provision()

ManagedEdge_check

POST /orgs/{orgId}/spaces/{spaceId}/domains/{domainId}/edge/check

Health-check the managed edge

client.managedEdge.check()

The Forumulate teamUpdated