Skip to content

ConceptFor module developers, site buildersDrupal 11

Multisite

Multisite runs several Drupal sites from one codebase: a single checkout of core, modules, and themes serves many sites, each with its own database, configuration, files, and domain, kept in its own directory under sites/.

Every Drupal request begins with the kernel choosing a site directory, and sites/default/ is the fallback that almost every project uses. Multisite is opting into that same mechanism with more than one directory: sites/intranet.example.com/ and sites/shop.example.com/ next to sites/default/, each holding its own settings.php.

What is shared is exactly the code: core, contributed and custom modules and themes, and vendor/. Everything stateful is per site: the database, the public and private files directories, the active configuration, and therefore which of the available modules each site has enabled.

The problem it solves is running many genuinely uniform sites (same modules, same release cadence) from one deploy artifact: a university’s department sites, a publisher’s brand sites. When the sites are not uniform, or isolation matters more than a shared checkout, separate projects are the better trade; containerized hosting has made them cheap.

sites/ is a router in the filesystem. The request’s host name selects a site directory; the site directory’s settings.php names a database; the database holds everything that makes that site itself. Code is shared, state is per site.

A multisite is therefore not one site with many domains. It is many complete, independent sites that happen to share a codebase, the way several applications can share one installed copy of a library.

Drupal\Core\DrupalKernel resolves the site directory on every request, and sites/sites.php is the switch it checks first: if the file does not exist, the kernel serves sites/default/ and looks no further. If it exists, the kernel builds candidate names from the request’s port, host, and path, most specific first (8080.shop.example.com, then shop.example.com, then example.com), and serves the first candidate that has a settings.php in its sites/ directory, falling back to sites/default/.

You create sites/sites.php by copying sites/example.sites.php, which ships with core and documents the format. An empty copy already turns multisite on: a directory named after its domain, such as sites/shop.example.com/, then matches with no further configuration. The file’s one job beyond existing is the optional $sites array, which maps a candidate name to a directory with a different name; that is how one directory serves both its production domain and a local development domain:

sites/sites.php
// shop.example.com and the local DDEV domain both serve sites/shop/.
$sites['shop.example.com'] = 'shop';
$sites['shop.ddev.site'] = 'shop';

Two more places core leans on the mechanism:

  • \Drupal\Core\Site\Settings is initialized from whichever settings.php the kernel selected, which is why every low-level switch (database credentials, trusted host patterns, the config sync directory) can differ per site.
  • Core’s own functional test runner is the busiest multisite user: every functional test creates a throwaway site under sites/simpletest/, isolated by the same site-directory mechanism, and deletes it when the test ends.

“sites/ is only for multisite.” Every Drupal site uses the site-directory mechanism; sites/default/ is the fallback candidate, not a special case. Multisite adds directories, it does not add the mechanism. Anatomy of a Drupal project places sites/ in the repository layout.

“Multisite divides the maintenance work.” It divides the checkouts, not the work. A code update lands on every site at the moment it is deployed, but database updates, configuration imports, and cache rebuilds run once per site: drush deploy needs --uri (or a site alias) per site, and a deploy is only done when it has succeeded on all of them. What the shared codebase actually removes is drift between sites, not steps.

“Sites on a multisite are isolated from each other.” They share one codebase and one PHP runtime. A fatal error in a shared custom module, a bad deploy, or a security update that needs testing hits every site at once. If failure isolation is the requirement, multisite is the wrong tool.

“Multisite shares users and content between sites.” Each site has its own database, so nothing is shared except code. Making one site’s content appear on another is ordinary integration work (JSON:API, feeds, or search indexes), not something the multisite mechanism provides.

Was this page helpful?

Drupal is a registered trademark of Dries Buytaert.