Federation
- Query Execution
- Schema Composition
- Query Optimization
- Common Types
- Entity Relationships
- Best Practices
- Troubleshooting
Query Planning
Router analyzes incoming queries and creates an execution plan:
- Parse Query: break down the query into field selections
- Identify Entities: determine which entities need to be resolved
- Plan Execution: create optimal execution order
- Execute Subqueries: send requests to appropriate subgraphs
- Compose Response: merge responses into final result
Query Execution
Based on the query execution plan generated by the router, the query could be executed sequentially or in parallel across multiple subgraphs. The router orchestrates the execution, ensuring that dependencies are resolved correctly.
Aspect | Rule | Details | Example |
---|---|---|---|
Type Merging | Types ( |
|
|
Field Uniqueness and Ownership | Each field on an object type must be "owned" by exactly one
subgraph, unless it's a |
|
|
Entity Extensions | Entities (types marked with |
|
|
Directive Validation | Federation-specific directives ( |
| |
Root Operation Type Merging (Query, Mutation, Subscription) | Root operation types ( |
|
|
Interface and Union Type Compatibility | When an interface or union type is merged or extended, all implementing types or member types must be resolvable and consistent across subgraphs. |
| |
Enum and Scalar Type Consistency | Enum and scalar types with the same name must have identical definitions (values for enums, and underlying serialization/deserialization logic for scalars) across all subgraphs. |
|
|
Schema Directives and Metadata | Directives defined at the schema level and other schema-level
metadata (like |
|
- Query Planning: optimize execution order
- Parallel Execution: execute independent subqueries in parallel
- Query Deduplication: cache and reuse identical queries
- Field Selection: only fetch requested fields
- Minimize Operations Spanning Multiple Subgraphs: design schemas to keep most queries within single subgraphs when possible, as cross-subgraph operations add query plan complexity and increase latency
- Overusing of @shareable and Shared Types: the
@shareable
directive enables multiple subgraphs to resolve the same entities or fields, offering query planner flexibility. However, overusing@shareable
can exponentially increase potential query paths, which degrades performance. Use it primarily where consistency between subgraphs is guaranteed and necessary - Schema Evolution and Compatibility: changes to fields and directives like
@requires
can impact current query plans and introduce latency. Manage schema migrations carefully, deploying them atomically to avoid disruptions or performance regressions - Query Caching: use caching mechanisms to store query for frequently static executed queries APQ (Automatic Persisted Queries)
- Query Complexity Analysis: analyze query complexity to prevent overly complex queries that can degrade performance. Implement limits on query depth and breadth
- Database Indexes: ensure that database queries are optimized with appropriate indexes to speed up data retrieval
Subgraph Caching
Aspect | DataLoader | Redis |
---|---|---|
Scope | Per-request, in-memory | Cross-request, distributed |
Pros |
|
|
Use Case | Batching and caching per-request data-fetch operations | Cross-service caching, Pub/Sub for subscriptions, message brokering |
Field | Description |
---|---|
scalar ID | Scalar type used to represent a unique identifier for a resource |
enum CountryCode | 2 letter ISO 3166 code representing a country |
enum LanguageCode | 2 letter ISO 639 code representing a language |
input PageInput | Input type for pagination parameters |
type PageInfo | Contains information about pagination, such as total count and whether there are more pages available |
Aspect | Definition | Example |
---|---|---|
Entity Definition and Keys | Entities are the core building blocks of federation. They represent business objects that can span multiple subgraphs |
|
Entity Extensions | Other subgraphs can extend entities to add domain-specific fields |
|
Single Subgraph One-to-One | Within a single subgraph, one entity can directly reference another entity |
|
Cross-Subgraph One-to-One | One entity in one subgraph can reference an entity in another subgraph using the @external directive |
|
Single Subgraph One-to-Many | Within a single subgraph, one entity can have multiple related entities |
|
Paginated One-to-Many | When one entity has many related entities, pagination is often used to efficiently fetch large sets of data |
|
Single Subgraph Many-to-Many | Within a single subgraph, one entity can be related to multiple instances of another entity |
|
Many-to-Many with Junction Table | In many-to-many relationships, a junction table is often used to represent the relationship between 2` entities |
|
Cross-Subgraph Entity Extension Pattern | Allows entities to be extended across subgraphs, enabling more flexible and modular architecture |
|
Cross-Subgraph Reference Resolution | Enables one subgraph to reference entities from another subgraph using a representation (primary key + typename). The _resolveReference resolver in each subgraph handles this, allowing distributed services to compose a unified API | Entity Definition and Key in the Products Subgraph
Reference Resolver in the Products Subgraph
Representing the Reference in the Reviews Subgraph
End-to-End Query
|
Required Fields Pattern | When an entity is extended across subgraphs, some fields may be required for resolution. The @requires directive specifies which fields must be available from the base entity to resolve the extended fields |
|
Interface-Based Polymorphism | Interfaces allow different subgraphs to define types that share a common contract, enabling polymorphic relationships |
|
Union-Based Polymorphism | Unions allow a field to return different types, enabling flexible relationships where the type is not known until runtime |
|
Conditional Access Control | Allows for fine-grained authorization based on user roles and permissions |
|
Dynamic Relationships | Relationships that depend on the current user context or other runtime conditions |
|
Aspect | Definition | Example |
---|---|---|
Entity Keys | Always use stable, immutable identifiers as entity keys |
|
Multiple Keys | Provide multiple key options for flexibility |
|
Design Minimal Entity Representations | Keep entity key fields minimal and avoid large objects |
|
Field's single Source of Truth | Each field should have a clear owner |
|
Use @shareable Judiciously | Only mark fields as @shareable when they truly can be computed by multiple subgraphs |
|
Schema Evolution: Use Deprecation Before Removal | Always deprecate fields before removing them |
|
Additive Changes Only | Make only additive changes to maintain compatibility |
|
Use Relay-Style Connections | Implement consistent pagination |
|
Domain-Driven Design Schema | Design your subgraph schemas around business domains, not technical boundaries |
|
Single Responsibility Principle | Each subgraph should own a specific set of related types and fields |
|
Schema Composition Issues
Category | Issue | Solution |
---|---|---|
Schema Composition | Invalid Federation Directives |
|
Inconsistent Entity Definitions |
| |
Missing @external Directive |
| |
Conflicting Field Definitions |
| |
Reference Resolution | Missing Reference Resolver |
|
Reference Resolver Returns Null |
| |
Incorrect Key Field Mapping |
|