Which Architecture When?
Apollo Federation v2, schema stitching and the Backend for Frontend pattern all solve the same underlying problem: coordinating distributed GraphQL data access. Which pattern fits when depends on team size, ownership boundaries and runtime requirements.
Table of Contents
- 1. The shared problem: coordinating multiple GraphQL sources
- 2. Apollo Federation v2: a distributed schema with clear ownership
- 3. Schema stitching: pragmatic but complex
- 4. Backend for Frontend: a purpose-built API layer
- 5. Decision framework: which pattern fits when
- 6. Gateway concepts and runtime requirements
- 7. Magento as a subgraph in a federation
- 8. Common pitfalls across all three patterns
- 9. Summary
- 10. Head to head: Federation vs. Stitching vs. BFF
- 11. FAQ
1. The shared problem: coordinating multiple GraphQL sources
If you run a single GraphQL schema maintained by one team, you need neither Federation nor stitching nor a BFF. These patterns arise from a concrete problem: multiple teams maintain separate services, each service has its own GraphQL API, and the frontend still needs to talk to a single endpoint. The three architecture patterns, Federation, stitching and BFF, solve this problem in different ways, with different trade-offs in complexity, ownership and runtime behavior.
In an e-commerce context this problem is particularly pronounced: product data comes from Magento, customer preferences from a CRM, reviews from a dedicated review service, stock levels from a WMS. The frontend needs data from all of these sources at once, ideally in a single request. Three requests from the browser to three different endpoints are not a solution, because they add up network latency and push coordination logic into the frontend.
2. Apollo Federation v2: a distributed schema with clear ownership
Apollo Federation is a standard for distributed GraphQL schemas in which each service (subgraph) owns part of the overall schema. A central router, the gateway, receives queries, breaks them down into sub-queries for the relevant subgraphs, merges the results and returns a single response. The key to Federation is the @key directive: it lets a subgraph reference entities from other subgraphs without having to import their entire schema.
Federation is a good fit when clear team ownership boundaries exist: team A owns the product subgraph, team B owns the customer subgraph. Each team can evolve its schema independently, as long as the declared entities and keys remain stable. The router knows the composed schema and plans query execution automatically. That is powerful, but also complex: Federation v2 with Apollo Router comes with its own concepts such as shareable fields, override directives and the query planner, which you need to understand before using it in production.
# Product subgraph (Magento or dedicated catalog service)
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3",
import: ["@key", "@shareable"])
type Product @key(fields: "sku") {
sku: String!
name: String!
price: Float!
}
type Query {
product(sku: String!): Product
products(search: String, pageSize: Int = 20): [Product!]!
}
# Review subgraph (separate service)
# extends Product from catalog subgraph
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3",
import: ["@key", "@external", "@requires"])
type Product @key(fields: "sku") {
sku: String! @external
reviews: [Review!]!
}
type Review {
id: ID!
rating: Int!
comment: String
}
3. Schema stitching: pragmatic but complex
Schema stitching is the older approach: multiple GraphQL schemas are programmatically assembled into a single one. Unlike Federation there is no formal standard, the composition happens in code, typically in Node.js using tools such as GraphQL Tools or The Guild's @graphql-tools/stitch. That makes stitching more pragmatic and quicker to set up than Federation, but also more prone to unexpected interactions when merging types from different sources.
Stitching is a good fit for situations where you need to merge several existing GraphQL APIs quickly, without being able to change the individual services. It suits smaller teams or internal platforms where ownership boundaries are less sharply drawn. The price is higher maintenance complexity in the stitching layer itself: type conflicts, schema evolution and caching are harder to control than in a Federation setup with a formal schema registry.
4. Backend for Frontend: a purpose-built API layer
The Backend for Frontend pattern (BFF) is not a GraphQL-specific concept, but it fits GraphQL very well: for each frontend, web app, mobile app, kiosk, a dedicated API layer is built that delivers exactly the data that frontend needs. In a GraphQL BFF, that means a dedicated GraphQL schema exposing only the fields relevant to that particular frontend, with resolvers that aggregate data from various backend services.
A BFF is not an alternative to Federation or stitching, but a complementary layer: the BFF can itself be a subgraph of a federation, or use schema stitching internally. The advantage of a BFF is maximum freedom in API design: the frontend team can shape its schema exactly as it fits the frontend, without having to consider the structure of the backend services. The downside: with multiple frontends you quickly end up with a zoo of BFFs, each developing its own business logic and hard to coordinate.
# BFF schema: optimized for the web storefront's homepage
# Aggregates data from catalog, promotions and recommendation services
type HomepageData {
hero_banner: HeroBanner
featured_products: [FeaturedProduct!]!
active_promotions: [Promotion!]!
personalized_recommendations: [ProductRecommendation!]!
}
type FeaturedProduct {
sku: String!
name: String!
image_url: String!
price: Float!
discount_percentage: Float
}
type HeroBanner {
headline: String!
subheadline: String
cta_label: String!
cta_url: String!
background_image_url: String!
}
type Query {
homepage: HomepageData!
@resolver(class: "BFF\\Web\\Resolver\\Homepage")
}
5. Decision framework: which pattern fits when
The choice between Federation, stitching and BFF depends on three factors: team size and ownership structure, runtime requirements and change frequency, and the existing technology stack. Federation requires teams to be willing to structure their services according to Federation standards, with @key directives, entity definitions and a schema registry. That is an investment that only pays off from a certain team size and system complexity onward.
Stitching is the fastest solution for merging several existing APIs without being able to change the services. It is not, however, a long-term architecture for large teams, because the central stitching layer can become a bottleneck and a black box. A BFF is the right choice when a frontend team needs to move quickly and independently, without waiting for backend service changes, even at the cost of possible logic duplication across multiple BFFs.
6. Gateway concepts and runtime requirements
The router or gateway in a federation is critical infrastructure: it receives all queries, plans execution across subgraphs, sends sub-queries and merges results. Apollo Router (implemented in Rust) is currently the most performant option for Apollo Federation. For smaller setups, Apollo Gateway (Node.js) is sufficient. Both have different caching, authentication and rate-limiting concepts that can be configured in the gateway, independent of the subgraphs.
Runtime requirements for Federation are higher than for a single GraphQL API: the gateway must be highly available, because it is a single point of failure for all frontends. Schema updates in subgraphs must be compatible before they are deployed, which is why schema registry workflows with breaking-change detection exist. These operational requirements are a frequently underestimated cost when getting started with Federation.
7. Magento as a subgraph in a federation
Magento can be integrated as a subgraph in an Apollo Federation, but not natively: Magento GraphQL does not support Federation directives out of the box. The solution is a thin proxy subgraph that exposes the Magento GraphQL schema externally while adding Federation-compatible @key directives. This proxy can be implemented in Node.js or PHP and translates between Magento's native GraphQL API and the Federation standard.
The more practical approach for most projects: Magento remains a standalone GraphQL endpoint, and a BFF layer aggregates Magento data with data from other sources. This pattern is simpler to operate and avoids the complexity of a full Federation setup, at the cost of a less formal separation of ownership. For pure headless commerce projects with a single frontend team, the BFF pattern is usually the more pragmatic choice.
# Thin federation-compatible proxy for Magento GraphQL
# Adds @key directives to make Magento types federation-aware
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.3",
import: ["@key"])
# Magento Product type exposed as federation entity
type MagentoProduct @key(fields: "sku") {
sku: String!
name: String!
price_range: PriceRange!
categories: [Category!]!
}
type PriceRange {
minimum_price: Price!
maximum_price: Price!
}
type Price {
final_price: Money!
regular_price: Money!
}
type Money {
value: Float!
currency: String!
}
type Query {
magentoProduct(sku: String!): MagentoProduct
magentoProducts(search: String, pageSize: Int = 20): [MagentoProduct!]!
}
8. Common pitfalls across all three patterns
With Federation, the most common pitfall is the unreflective use of @extends for entities that should actually be @key entities with @external fields. Federation v2 has simplified these concepts, but the learning curve is steep. A second pitfall is missing schema registration before deploy: whoever changes subgraph schemas without validating them against the router's composition check risks a gateway failure that hits all frontends at once.
With stitching, the most common problem is the silent overwriting of fields: if two schemas define a type with the same name but different fields, one of the schemas wins depending on configuration and the other's fields are silently dropped. With BFF, the most common problem is business logic duplication: each BFF reimplements the same validation rules, which leads to inconsistencies between frontends whenever the rules change.
9. Summary
Federation, stitching and BFF are not competing standards, but complementary tools for different situations. Federation is the right choice for large platforms with several autonomous teams and clear service ownership boundaries. Stitching fits fast integration of existing APIs without changing services. The BFF pattern is optimal for fast, frontend-centric development, where a dedicated team should fully control the API layer.
The most important takeaway: all three patterns increase system complexity compared to a single GraphQL endpoint. That complexity is justified when the underlying problems, distributed teams, separate services, differing frontend requirements, are real and lasting. Whoever adds complexity before the problem is real pays the price without getting the benefit.
Federation, Stitching and BFF: The Essentials at a Glance
Federation
For large platforms with autonomous teams. Formal standard, schema registry, gateway as critical infrastructure. High complexity, high scalability.
Stitching
Pragmatic integration of existing APIs without service changes. Quick to get started, but higher maintenance risk as complexity grows.
BFF
Purpose-built API layer for a specific frontend. Maximum freedom, risk of logic duplication across multiple frontends.
Magento
Not natively a Federation subgraph. A proxy approach or a BFF is more pragmatic. A standalone endpoint often remains the simplest solution.
10. Head to head: Federation vs. Stitching vs. BFF
| Criterion | Federation | Stitching | BFF |
|---|---|---|---|
| Ownership | Team per subgraph | Central stitching team | Frontend team |
| Complexity | High (gateway, registry) | Medium | Low to medium |
| Scalability | Very high | Medium | Per frontend |
| Entry barrier | High | Medium | Low |
| Magento integration | Proxy required | Directly possible | Directly possible |