How Multi-Tenant CMS Works

How one Worker manages multiple client sites independently — domain lookup, isolation, and new client setup.

Multi-tenant CMS architecture diagram

The most common question about AstroForge is: "How do you manage different client sites from a single CMS system?" The answer lies in how Cloudflare Workers operate.

Domain → Client Lookup

Every client site has its own custom domain registered in Cloudflare Pages. When a client visits /cms, the browser request is forwarded through Cloudflare Pages Functions to the astrocms Worker. In this relay, an x-forwarded-host header is added — for example, client-a.com.

The Worker reads this header and runs SELECT * FROM clients WHERE domain = 'client-a.com' against the D1 database. No match returns 404. A match sets that client's GitHub repo details into the request context.

Isolation Guarantee

Client lookup happens on every request — there's no persistent tenant binding at the session level. A valid session token for Client A won't work on a request arriving with Client B's domain header.

The GitHub PAT is shared across all tenants — this is a known limitation. GitHub fine-grained PATs allow per-client-repo token scoping, which is recommended for security.

Adding a New Client

To add a new client, run register-client.ts in the astrocms repo. This script generates the SQL to insert into D1. Paste the SQL into Cloudflare Dashboard → D1 → Console. Then add the custom domain in Cloudflare Pages. The entire onboarding takes under 5 minutes.

Conclusion

Multi-tenant architecture means agencies never need to set up a separate CMS for each client. One Worker, one D1, unlimited clients — with complete isolation.