Extending types across subgraphs¶
One of the main benefits of Fusion is the ability to compose data that lives in different services into a single GraphQL graph. Instead of duplicating data or creating direct service dependencies, a service can contribute additional fields to an entity defined in another subgraph.
Why extend types?¶
In a microservices architecture, a business entity often spans multiple bounded contexts. For example, a LandingRequest might be defined in one service, while tracking information about it lives in a completely separate Tracking service.
Without type extensions, you'd have two options — both problematic:
- Duplicate the data: the Tracking service re-exposes
LandingRequestfields that belong to a different service. - Create a direct dependency: one service calls the other internally, coupling them together.
Type extensions solve this by letting the Tracking service contribute fields to LandingRequest without redefining it. Fusion handles the composition at the gateway level, presenting a unified type to clients.
How it works¶
A service that wants to contribute fields to an entity defined elsewhere needs two things:
- An
[ObjectType]that holds only the minimum information needed to identify the entity, plus the new fields being contributed. - A
[Lookup]resolver that tells Fusion how to create a minimal reference to the entity so it can delegate resolution of those fields to this service.
Example: Tracking service extending LandingRequest¶
A few things to note:
- The
[ObjectType]record contains the minimum information required to identify the entity (CorrelationIdin this example) as well as any fields contributed by this subgraph. It should not duplicate fields owned by other subgraphs, as doing so introduces redundancy and may lead to composition conflicts. - The
[Parent]parameter inTracking(...)receives the resolvedLandingRequestinstance, making its identity properties available to fetch related data. - The
[Lookup]resolver creates a minimalLandingRequestreference — it doesn't load real data, it just gives Fusion the identity it needs to delegate resolution oftrackingto this service. - The
[Internal]attribute ensures the lookup is not exposed to GraphQL clients — it exists exclusively for Fusion's internal composition and entity resolution.
During schema composition, Fusion merges both definitions into a single LandingRequest type exposed by the gateway.
Auto-discovery with [ObjectType]¶
Any type decorated with [ObjectType] is automatically discovered by the Suite GraphQL infrastructure. This means types contributing fields to an existing entity do not need to be manually registered in the service's GraphQL configuration.
| C# | |
|---|---|
This keeps the extending service's configuration clean and avoids boilerplate.
How resolution works at runtime¶
When a client queries data that spans multiple subgraphs:
Fusion uses the [Lookup] resolver in the Tracking service to create a minimal LandingRequest reference, then delegates resolution of the tracking field to that service. From the client's perspective, the data looks like a single unified object — even though it was resolved by two different services.
When to use type extensions¶
Type extensions are the right tool when:
- A business entity spans multiple bounded contexts.
- Additional information belongs to a different service than the one that defined the entity.
- Multiple services need to contribute fields to the same GraphQL type.
- You want to expose a unified API without introducing direct service-to-service dependencies.