One engine, many domains
The multi-tenant pattern behind a sports network, a 50-state platform, and a family of atlases: one backend and one frontend serving many public sites.
By Andrew J. Pyle
The first time I built a good site, it was a project. The second time I wanted a nearly identical site for a different subject, I almost rebuilt the whole thing from scratch before I stopped and asked the only question that matters: what is actually different between these two?
The answer was almost nothing. This is the multi-tenant pattern I use across several networks: one engine, many domains, where standing up the next site is a configuration change, not a new codebase.
01A NETWORK IS NOT N WEBSITES
The wrong unit of work
The first time I built a good site, it was a project. The second time I wanted a nearly identical site for a different subject, I almost rebuilt the whole thing. Then I asked the only question that matters at that point: what is actually different between these two?
The answer was almost nothing. The data was different. The colors were different. Everything underneath was the same. That gap, between what changes and what I was about to rewrite, is where the real work lives.
A network is not N websites. It is one machine that builds websites. Stop building sites. Build the thing that stands them up.
02DATA, THEME, COPY
What actually differs per tenant
Once you look honestly at two near-identical sites, the list of real differences is short. Everything else belongs in the shared core.
| Per tenant | Shared engine |
|---|---|
| The data for this subject | The models and the data layer |
| The theme and colors | The components and page templates |
| The copy and the domain | Routing, rendering, SEO, deploy |
If something that should be shared is living inside one tenant, that is a bug, even if the site works. The discipline is keeping tenant-specific things out of the core.
03REFACTOR BECOMES PLATFORM
The extraction is the product
The platform is rarely designed up front. It is extracted. You build one site, then a second that is almost the same, and the refactor that pulls the shared parts out is the moment you stop having a site and start having a platform.
After that, standing up the next site is a configuration change, not a new codebase. New data, new theme, new domain, same engine. That is the asset.
04THE TRADE-OFFS
What you buy, and what it costs
What you buy is leverage. One improvement to the engine lifts every site at once. One bug fix fixes the whole network. The marginal cost of the next site drops toward the cost of its data.
What it costs is discipline. A shared engine means a mistake is shared too. Every change is a change to all tenants, so you test like it matters, and you keep the per-tenant surface as thin as the real differences.
05THE PART NOBODY TALKS ABOUT
Do not extract too early
The opposite mistake is just as expensive: building a platform for a single site. Abstraction you do not need yet is a tax you pay on every change with no network to spread it across.
Wait for the second, ideally the third, near-identical site. Let the real duplication tell you what to extract. The pattern earns its keep only once there is more than one tenant to carry it.
06NEXT STEPS
How to start
- Take two sites you would build the same way and write down what is actually different.
- If the list is only data, theme, and copy, you have a tenant model, not two projects.
- Extract the shared core only when the duplication is real, not anticipated.
- Make the next site a configuration change, and keep the per-tenant surface thin.