PATTERN Cited by 1 source
Multi-tenant GraphQL runtime¶
When to use¶
You have:
- Many teams wanting to contribute to one GraphQL schema.
- Pressure to avoid running one GraphQL server per contributing team (Federation's cost) and also to avoid one giant codebase that every team commits into (UBFF's shared release train).
- A platform team that can build and operate a shared runtime.
- Domain teams that don't want to operate GraphQL infrastructure.
The pattern¶
One shared multi-tenant runtime hosts many independently developed and tested tenant modules, each owning a portion of the schema. The tenant module is the unit of decentralisation (see patterns/module-based-graphql-decentralization).
The contribution contract¶
A tenant team's contract is intentionally minimal — the canonical formulation from Viaduct's 1.0 announcement (verbatim): "A team wanting to contribute simply creates a directory for their module, defines their schema definition language (SDL) and resolvers, and they are ready to serve. There is no need to set up or operate a separate GraphQL service, manage router composition, or become experts in GraphQL infrastructure. Teams focus on domain logic; the platform handles execution, scaling, and integration." (Source: sources/2026-05-13-airbnb-viaduct-1-0-and-the-future-of-airbnbs-data-mesh)
The module:
- A directory in the runtime's codebase.
- An SDL declaring the module's Types / Queries / Mutations.
- Resolvers implementing the contract.
The runtime:
- Execution — runs the module's resolvers on incoming requests.
- Scaling — handles capacity for the shared substrate; tenant modules don't scale themselves.
- Integration — composes module SDLs into the runtime's global schema; routes incoming GraphQL requests to the right module's resolvers.
- Multi-tenancy — isolates tenant modules' state, observability, and (ideally) blast radius from each other.
Topology¶
clients
│
▼
┌───────────────────────┐
│ multi-tenant GraphQL │
│ runtime │
│ │
│ ┌───────┐ ┌───────┐ │
│ │tenant │ │tenant │ │
│ │module │ │module │ │
│ │ A │ │ B │ │
│ └───┬───┘ └───┬───┘ │
│ │ │ │
│ ┌───┴───┐ ┌───┴───┐ │
│ │tenant │ │tenant │ │
│ │module │ │module │ │
│ │ C │ │ D │ │
│ └───────┘ └───────┘ │
└───────────────────────┘
Canonical wiki instance: Viaduct¶
Viaduct is the canonical wiki instance. Airbnb's GraphQL data-oriented service mesh runs as a multi-tenant runtime hosting tenant modules contributed by many teams across the company; the 1.0 announcement (2026-05-13) released it as open source on Maven Central.
The pattern's load-bearing framing quote, verbatim from the same post: "Federation distributes development through services. Each team owns and operates its own GraphQL subgraph server; those subgraphs are composed by a federation router into a single unified graph. Viaduct distributes development through modules. A shared multi-tenant runtime hosts tenant modules that define and implement portions of the schema."
Trade-offs vs adjacent patterns¶
Three GraphQL decentralisation topologies sit on the wiki: UBFF (see patterns/unified-graphql-backend-for-frontend + Zalando UBFF as the canonical instance); the multi-tenant runtime (this pattern + Viaduct as the canonical instance); and Federation (see patterns/federated-graphql-subgraph-per-domain + Yelp CHAOS on Apollo Federation as the canonical instance). Their trade-offs:
| Property | UBFF (one service, one module) | Multi-tenant runtime (Viaduct) | Federation (many services, one module each) |
|---|---|---|---|
| Servers per organisation | 1 | Few (one per Viaduct instance) | Many (one per subgraph) |
| Modules per server | 1 (the whole graph) | Many | 1 |
| Per-team operational cost | Low (no server to operate) | Low (no server to operate) | High (each team owns a subgraph server) |
| Per-team release autonomy | Low (shared release train) | Medium (shared per-runtime) | High (each team deploys independently) |
| Cross-team blast radius | High (single deploy) | Medium (per-runtime deploy) | Low (per-subgraph) |
| Composition complexity | None | Module composition inside runtime | Federation router composition |
The multi-tenant runtime pattern lives between UBFF and Federation on every axis. It collapses Federation's per-team server cost (good) at the price of giving up Federation's per-team deploy independence (a runtime-level deploy moves all its tenant modules together).
Composition with Federation¶
Multi-tenant runtimes and Federation are complementary: a multi-tenant runtime can participate as a subgraph inside a federated supergraph. The Viaduct post names this directly: "In a large organization where hundreds of teams contribute to the overall graph, a federated approach requires running hundreds of independent subgraph servers. With Viaduct, organizations can instead run a smaller number of Viaduct instances, each hosting many closely related tenant modules. Federation can then compose those instances into a larger enterprise graph."
enterprise Federation router
│
┌───────────────┼───────────────┐
▼ ▼ ▼
Viaduct A Viaduct B Viaduct C
┌───────┐ ┌───────┐ ┌───────┐
│mods │ │mods │ │mods │
│ 1-10 │ │ 11-20 │ │ 21-30 │
└───────┘ └───────┘ └───────┘
Compared with N × M independent subgraph servers, this collapses the operational cost by a factor of M while preserving cross-organisation composition at the router.
Hard problems this pattern introduces¶
- Per-module isolation boundary. A bad / runaway / leaking resolver in module A must not take down module B. The runtime must enforce per-module CPU / memory / time / connection budgets — and there's no out-of-the-box solution. The Viaduct GraphQLConf 2026 talk "Sharding a GraphQL Gateway for Blast Radius Reduction" (Linquan Zhang & Cetin Sahin, 2026-05-20) is the explicit follow-up on this.
- Per-module observability. Whose alert fires and who pays for the cost of a query that crosses module boundaries is non-obvious. Built-in ownership tags + cost-aware tracing are the disclosed-but-not-detailed answer (see Viaduct's GraphQLConf 2026 talk "Observability for a Multi-Tenant GraphQL Gateway at Scale" by Vickey Yeh).
- Schema composition across modules. When two modules
declare the same Type, or one module's Query references
another's Type, the runtime needs deterministic composition
rules. UBFF avoids this (one schema source); Federation
formalises it (
@key,@external,@requiresdirectives); multi-tenant runtimes need their own variant. - Release-train coupling within a runtime. Tenant modules inside the same runtime share a deploy. The pattern only helps team-autonomy along one axis: it removes the "operate-a-server" tax, but it doesn't remove the "deploy-with-others" coupling.
- Cross-runtime composition still needs Federation. If you need true cross-runtime ownership autonomy, you re-introduce the Federation router. The pattern is most attractive when most contributing teams can fit into a small number of related runtimes.
Trade-offs not solved by the pattern¶
- GraphQL caching is hard. Multi-tenant runtimes don't change this — every query is still a unique URL+body, so a GraphQL-aware caching layer is still required.
- Resolver fan-out is still a footgun. A naive multi-module query can hit many backends; protect with DataLoader + depth / complexity limits, same as any GraphQL deployment.
- Schema governance is still load-bearing. Who can declare a Type, who must approve a deprecation, what naming is allowed — none of these are solved by switching to a multi-tenant runtime.
Seen in¶
- sources/2026-05-13-airbnb-viaduct-1-0-and-the-future-of-airbnbs-data-mesh — first canonical wiki naming via Viaduct's 1.0 announcement. Viaduct is the canonical wiki instance.
Related¶
- systems/viaduct — the canonical instance
- systems/graphql — the substrate
- systems/apollo-federation — the many-server alternative
- the cross-runtime composition layer
- systems/zalando-graphql-ubff — the single-module alternative
- concepts/data-oriented-service-mesh — the architectural shape
- concepts/decentralized-development-of-central-schema — the problem space
- patterns/module-based-graphql-decentralization — the contribution model that makes the pattern workable
- patterns/graphql-unified-api-platform — the umbrella
- patterns/federated-graphql-subgraph-per-domain — Federation's pattern
- patterns/unified-graphql-backend-for-frontend — UBFF's pattern