Shared types across subgraphs in GraphQL - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When using shared types across subgraphs in GraphQL, it's important to understand how the execution time changes as the number of subgraphs and shared types grow.
We want to know how the system handles queries involving these shared types as the input size increases.
Analyze the time complexity of this GraphQL schema snippet using shared types across subgraphs.
type Product @key(fields: "id") {
id: ID!
name: String
price: Float
}
extend type Review @key(fields: "id") {
id: ID! @external
product: Product @requires(fields: "productId")
}
This snippet shows a shared type Product used in multiple subgraphs, with Review extending it by referencing Product.
Look for repeated actions that affect performance.
- Primary operation: Resolving shared type fields across subgraphs during query execution.
- How many times: Once per query involving the shared type, and once per related entity that references it.
As the number of entities referencing shared types grows, the operations increase proportionally.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 resolutions of shared type fields |
| 100 | About 100 resolutions |
| 1000 | About 1000 resolutions |
Pattern observation: The number of operations grows linearly with the number of entities referencing the shared type.
Time Complexity: O(n)
This means the time to resolve shared types grows in direct proportion to how many related entities are queried.
[X] Wrong: "Resolving shared types happens only once, so it doesn't affect performance much."
[OK] Correct: Each entity referencing the shared type triggers its own resolution, so the cost adds up with more entities.
Understanding how shared types affect query execution helps you design efficient GraphQL schemas and anticipate performance as your data grows.
What if we cached shared type resolutions? How would that change the time complexity?
Practice
@key in shared types across GraphQL subgraphs?Solution
Step 1: Understand the role of
The@key@keydirective marks fields that uniquely identify an entity across subgraphs, enabling them to share the same type.Step 2: Differentiate from other directives
Other directives like@externalor@deprecatedserve different purposes, not unique identification.Final Answer:
To mark fields that uniquely identify an entity across subgraphs -> Option AQuick Check:
@keymarks unique identifiers [OK]
- Confusing @key with @external
- Thinking @key marks optional fields
- Assuming @key defines data types
Solution
Step 1: Identify the directive for external fields
The@externaldirective marks fields that are owned by another subgraph but referenced in the current one.Step 2: Differentiate from other directives
@keymarks unique identifiers,@requiresand@providesrelate to field dependencies, not external ownership.Final Answer:
Use@externaldirective on the field -> Option DQuick Check:
@externalmarks fields from other subgraphs [OK]
- Using @key instead of @external
- Confusing @requires with @external
- Not marking external fields at all
type Product @key(fields: "id") {
id: ID!
name: String
price: Float @external
}Which statement is true about the
price field?Solution
Step 1: Analyze the
The@externaldirective onprice@externaldirective meanspriceis not owned here but comes from another subgraph.Step 2: Understand the role of
The@keyonididfield is the unique identifier, sopriceis not an ID.Final Answer:
It is defined in another subgraph and referenced here -> Option CQuick Check:
@externalmeans field is from another subgraph [OK]
- Thinking @external means field is owned here
- Confusing @key with @external
- Assuming @external means deprecated
type User @key(fields: "userId") {
userId: ID!
email: String @external
name: String
}Which statement is true about the
email field?Solution
Step 1: Analyze the
The@externaldirective onemail@externaldirective meansemailis defined in another subgraph and referenced here.Step 2: Differentiate from other fields
userIdis the@keyfield provided locally,nameis owned locally (no directive).Final Answer:
It is defined in another subgraph and referenced here -> Option AQuick Check:
@externalmeans field from another subgraph [OK]
- Thinking @external means owned locally
- Believing @key must include all fields
- Assuming all fields need @external
Book type. Subgraph A defines:type Book @key(fields: "isbn") {
isbn: ID!
title: String
}Subgraph B defines:
extend type Book @key(fields: "isbn") {
isbn: ID! @external
author: String
}Which statement best describes how these shared types work together?
Solution
Step 1: Identify ownership of fields
Subgraph A definesBookwithisbnandtitle, so it owns these fields.Step 2: Understand extension in Subgraph B
Subgraph B extendsBook, markingisbnas@external(owned by A) and addsauthor.Step 3: Confirm no conflicts
Using@keywith the same fieldisbnallows both subgraphs to share the type without conflict.Final Answer:
Subgraph A ownsisbnandtitle, Subgraph B extendsBookusingisbnas key and addsauthor-> Option BQuick Check:
Extension uses @external keys to share types [OK]
- Thinking both subgraphs own the same key field
- Believing extension requires redefining all fields
- Assuming conflicts occur with shared keys
