How the Fission Algorithm Works: Top-Down GraphQL Federation Design

Jens Neuse
TL;DR
Fission inverts GraphQL Federation. Instead of composing subgraphs into a supergraph, you design the supergraph first and Fission decomposes it into subgraph specs, handling entity keys, directives, and validation automatically.
In a previous post , I argued that Federation's composition model is backwards. It builds the supergraph from the bottom up when it should be designed from the top down.
This post is a technical deep dive into how the Fission algorithm actually does that.
Introducing WunderGraph Hub: Rethinking How Teams Build APIs
WunderGraph Hub is our new collaborative platform for designing, evolving, and shipping APIs together. Itβs a design-first workspace that brings schema design, mocks, and workflows into one place.
To understand Fission, first you need to understand what makes schema changes expensive in Federation.
Consider a federated graph with three subgraphs:
Composition produces a supergraph where you can query:
Now a frontend team wants to add shipping tracking. This is their dream query :
In the traditional workflow, the frontend team has to figure out:
shippingshould be a field onOrder, but which subgraph ownsOrder?- Both the Orders subgraph and the Products subgraph define
Orderas an entity. carrierandtrackingNumbercome from the shipping provider.estimatedDeliverymight come from logistics.currentLocationrequires real-time tracking data.- Should this be a new subgraph? An extension of Orders? Both?
The frontend team can't answer these questions, so the platform team needs to be brought in. Meetings are scheduled and the process begins.
Fission automates the hardest parts of this process.
Before we walk through an example, it's important to understand what Fission is and what it isn't.
Fission is not just the opposite of composition, a batch algorithm that takes a supergraph and splits it into subgraphs. It's a stateful schema graph engine, an in-memory system that maintains two synchronized views of your federated graph at all times:
- The supergraph view β the unified, consumer-facing schema. This is the canonical source of truth for what the API looks like.
- The subgraph views β one per service, representing what each team is responsible for implementing.
These two views are kept in sync. When you make a change to either one, Fission will automatically propagate the consequences: renaming a type cascades to every subgraph and every field reference. Adding a type to a subgraph pulls in all its transitive dependencies. Entity @key directives propagate automatically. @shareable directives are added bidirectionally when fields exist in multiple subgraphs.
Every edit follows the same pattern: validate first, mutate second, update indexes, and return a structured result. If validation fails, no state changes happen. This ensures you never have a half-applied edit.
The key insight is the synchronization contract:
The supergraph view represents the union of all subgraph views, plus any types and fields not yet assigned to a subgraph.
This means the architect can design the complete API shape first and then decide how to distribute the implementation across subgraphs. The supergraph doesn't have to be assembled from the bottom up. It can be designed from the top down.
Let's walk through the shipping example step by step.
The architect adds the new types and fields directly on the supergraph:
At this point, ShippingInfo exists in the supergraph but isn't assigned to any subgraph yet. The shipping field on Order is defined but no team is responsible for implementing it.
The supergraph is the API you want.
The architect assigns the new type to an existing subgraph, or if necessary, creates a new one.
Let's say they assign ShippingInfo and the shipping field on Order to a new "Shipping" subgraph.
When this happens, Fission automatically does several things:
Transitive dependency propagation: ShippingInfo references String, DateTime, and Boolean. These are all scalars that are already available. But if ShippingInfo had a field like warehouse: Warehouse!, and the Warehouse type doesn't exist in the Shipping subgraph yet, Fission will automatically pull it in, along with anything Warehouse references. This propagation is cycle-safe; mutual type references don't cause infinite loops.
Entity key propagation: Order is an entity with @key(fields: "id") in the Orders and Products subgraphs. When the Shipping subgraph extends Order, Fission automatically adds @key(fields: "id") to the Shipping subgraph's Order definition. The entity remains resolvable across subgraph boundaries.
Shareable propagation: If the shipping field ends up defined in multiple V2 subgraphs, @shareable is added bidirectionally to all subgraphs containing that field, not just the new one. This ensures the rendered SDL is always valid for composition.
Every edit is validated before it's applied.
Fission enforces a comprehensive set of invariants:
- Reference integrity: you cannot remove a type that's still referenced by other fields. The error includes the exact coordinates that still reference it.
- Last-child protection: you cannot remove the last field from a type that's still referenced elsewhere.
- Key field validity: you cannot rename or change the type of a field that participates in a
@keyfield set. The key selection tree would break. - Type-kind compatibility: you cannot have
Useras an Object in one subgraph and an Interface in another. - Interface consistency: when a type implements an interface, it must have all the interface's fields with compatible types.
If any validation fails, the edit is rejected and the state remains unchanged. The error message includes enough information for the Hub UI to show exactly what went wrong and suggest a fix.
Renaming is the most complex operation, and it's where Fission's reference tracking really shines.
When a type is renamed at the supergraph level β say Order becomes CustomerOrder β Fission cascades the rename:
- Every subgraph containing
Orderhas its node renamed - Every field typed as
Orderor[Order!]!is updated - Every
@keyfield set referencingOrderis regenerated from its selection tree - Interface implementations and union memberships are updated
- All reverse indexes are re-keyed
The SDL is not stored as text, it's regenerated from structured state. This means @key(fields: "id") always reflects the current field names. If you rename the id field to orderId, the key directive automatically becomes @key(fields: "orderId").
Let's trace through a more complex scenario to see how these steps work together.
Starting state: the three subgraphs from above (Users, Orders, Products).
Dream query:Three new capabilities: inventory, shipping, and payment.
Step 1: Design on the supergraphThe architect adds all new types and fields to the supergraph:
Product.inventory: InventoryInfo!(new field on existing entity)InventoryInfowithinStockandwarehouseLocation(new type)Order.shipping: ShippingInfo!(new field on existing entity)ShippingInfowithcarrier,trackingNumber,estimatedDelivery(new type)Order.payment: PaymentInfo!(new field on existing entity)PaymentInfowithmethod,last4,receiptUrl(new type)Query.order(id: ID!): Order(new root field)
At this point, the supergraph describes the ideal API. None of these new types are assigned to subgraphs yet.
Step 2: Assign to subgraphsThe architect assigns each new type to a subgraph on the Hub canvas:
| New item | Assigned to | What Fission automates |
|---|---|---|
InventoryInfo + Product.inventory | New Inventory subgraph | Product @key(fields: "id") is propagated to the Inventory subgraph. Product entity is automatically resolvable. |
ShippingInfo + Order.shipping | New Shipping subgraph | Order @key(fields: "id") is propagated. If ShippingInfo referenced other types, they'd be pulled in transitively. |
PaymentInfo + Order.payment | New Payments subgraph | Order @key(fields: "id") is propagated. |
Query.order | Orders subgraph | Orders already owns the Order entity. Field is added, references are tracked. |
The architect decides that Product.inventory goes to a new Inventory subgraph because the Products team doesn't have warehouse data.
Every assignment is validated as it happens:
- Entity keys are resolvable across the new subgraph boundaries
- No type-kind conflicts (e.g.,
Orderis an Object in all subgraphs) - Naming conventions pass (Hub's governance layer flags
inStockβ should it beisInStock? Architect approves the exception) - Reference integrity is maintained
If the architect tried to assign ShippingInfo to a subgraph in a way that would break composition, the edit would be rejected with a specific error before any state changes.
At any point, Fission can render valid GraphQL SDL from structured state. This means the output reflects every cascading update, renamed field, and propagated directive.
Subgraph SDL SpecificationsFor each affected subgraph, Fission renders the exact SDL that the team needs to implement:
Each new subgraph automatically includes @key(fields: "id") on the entities it extends, because Fission propagated these from the existing subgraphs.
Fission can also render the full supergraph SDL at any time. The architect can verify that the dream query will actually work before any code is written. Because the supergraph is the source of truth, not a composition result.
A few architectural choices in Fission that are worth explaining:
The supergraph is the source of truth. In traditional Federation, the supergraph is a side effect of composition. In Fission, it's the canonical representation. Removing a type from a subgraph does not remove it from the supergraph. You can design the complete API shape first, then decide how to distribute implementation. This is backwards from composition.
Fission automates consequences, not decisions. The architect decides where types and fields belong. Fission automates everything that follows: transitive dependency propagation, entity key propagation, @shareable management, reference tracking, and cascading renames. The goal is to automate the mechanical work and surface the judgment calls to humans.
Validate first, mutate second. Every edit validates all preconditions before making any state change. If validation fails, the state is unchanged. Because invalid states are caught at design time, the "composition fails after three teams implement their parts" scenario is prevented.
Federation directives are structured state, not text. @key, @shareable, @inaccessible, @override, and @provides are modeled as structured state with their own selection trees, indexes, and validation rules. When you rename a field that participates in @key(fields: "id name"), the key field set is automatically updated.
Fission tracks the full lifecycle. From proposal to review to implementation to composition, the entire workflow is tracked in one place. When a subgraph team ships their implementation, it's checked against the original specification. The proposal isn't complete until all specifications are met and the final composition succeeds.
Fission is the algorithmic counterpart to Hub's collaboration model.
Hub provides the canvas, the collaboration workflow, and the governance layer. Fission provides the ability to take a high-level design intent and translate it into concrete, actionable subgraph specifications.
Together, they make it possible to design like a monolith and implement as microservices .
The supergraph is designed as a coherent whole. The implementation is distributed across teams. The algorithm handles the translation between the two.
If you want to see Fission in action, watch the webinar or schedule a walkthrough .
Frequently Asked Questions (FAQ)
Fission is a stateful schema graph engine that maintains two synchronized views of a federated GraphQL schema β the supergraph and the subgraphs. It inverts the traditional Federation workflow: instead of composing subgraphs into a supergraph, you design the supergraph first and Fission handles the decomposition into subgraph responsibilities, including cascading updates, dependency propagation, and federation directive management.
No. Fission operates at design time β it determines what each subgraph should implement. Federation composition still operates at build time β it merges implemented subgraph schemas into the runtime supergraph. Fission feeds into composition, not replaces it.
Yes. Fission can import an existing federated graph, represent it on the Hub canvas, and then decompose proposed changes while respecting the existing structure and ownership.
The architect decides which subgraph should own a new field via the Hub canvas. Fission then automates everything that follows: propagating transitive type dependencies, adding entity keys, managing @shareable directives across subgraphs, and validating that the result will compose correctly. Fission automates the mechanical consequences and surfaces the judgment calls to the architect.
Jens Neuse
CEO & Co-Founder at WunderGraph
Jens Neuse is the CEO and one of the co-founders of WunderGraph, where he builds scalable API infrastructure with a focus on federation and AI-native workflows. Formerly an engineer at Tyk Technologies, he created graphql-go-tools, now widely used in the open source community. Jens designed the original WunderGraph SDK and led its evolution into Cosmo, an open-source federation platform adopted by global enterprises. He writes about systems design, organizational structure, and how Conway's Law shapes API architecture.

