Skip to content

ADR 0007 — Multisite policy

Status: accepted Date: 2026-08-21

Context

WordPress multisite allows a plugin to be network-activated or activated per site, and state can live per blog or network-wide. Licensing has to pick one and be consistent, because a mixed model is worse than either choice.

The Phase 0 audit answered most of this. The plugin is already uniformly per-site:

  • Core\WpOptions wraps get_option exclusively. There is no *_site_option call anywhere in src/.
  • Activator installs the schema per blog and hooks wp_initialize_site so a new blog gets its own tables.
  • Uninstaller iterates blogs and purges each one independently.
  • Every table is prefixed with the blog's $wpdb->prefix.

Decision

Licensing follows the existing model. Per-site scope, without exception.

AspectPolicy
Network activationSupported. Each blog activates independently
Site-specific activationSupported, identical code path
Licence scopePer blog
Installation UUID scopePer blog
Installation token scopePer blog
OptionsPer blog, via get_option
Cron eventPer blog
Network admin screenNot implemented

Each blog reports is_multisite, blog_id and network_home_url in every request, so the platform can recognise that twenty installations belong to one network and bill them as one customer if the product decides to. That decision belongs on the platform, not in the plugin.

One licence key may be entered on several blogs. Whether that is within the plan is the API's call, exactly as it is for separate single-site installs.

Consequences

Good:

  • Zero new concepts. Licensing behaves like every other part of the plugin.
  • Per-blog uninstall keeps working, including the opt-in purge.
  • No blog can affect another blog's entitlements.
  • A network admin screen can be added later as a read-only overview without changing the storage model.

Costs:

  • A 200-site network needs 200 activations unless the platform recognises the network and bills it as one customer. This is a pricing decision, and the signals to make it are already transmitted. Recorded as risk R-10 in the Phase 0 audit.
  • 200 blogs mean 200 cron events and 200 daily API calls. Bounded by the UUID-derived jitter, which spreads them across a three-hour window rather than firing together.
  • A network administrator has no single screen showing every blog's licence.

Rejected

Network-wide licence in wp_sitemeta. It would be the only network-scoped state in the plugin, breaking the symmetry the rest of the code relies on. It would also break the per-blog uninstall path, and it would let one blog's administrator disconnect a sibling blog's licence — a privilege escalation between tenants that a per-site model does not have.

Network-only activation. Forces a model on customers running multisite for unrelated reasons, and there is no technical need for it.

A hybrid: network licence with per-blog override. Two sources of truth for the same question. The audit explicitly warned against a "random mixed solution", and this is exactly that.

Counting a network as one installation locally. The plugin would be deciding its own limit, which contradicts ADR 0001.

Digitale Lösungen. Persönlich. Zukunftssicher.