Bird
Raised Fist0
GraphQLquery~10 mins

Shared types across subgraphs in GraphQL - Step-by-Step Execution

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Concept Flow - Shared types across subgraphs
Define shared type in Subgraph A
Define shared type in Subgraph B
Mark type as @key in each subgraph
Gateway composes subgraphs
Shared type resolved across subgraphs
Queries can access combined fields
Shared types are defined in multiple subgraphs with matching keys, then composed by the gateway to allow queries accessing combined fields.
Execution Sample
GraphQL
type Product @key(fields: "id") {
  id: ID!
  name: String
}

extend type Product @key(fields: "id") {
  id: ID! @external
  price: Float
}
Defines a shared Product type in two subgraphs, one with 'name', another extending it with 'price'.
Execution Table
StepActionSubgraph A Type StateSubgraph B Type StateGateway Composition Result
1Define Product type with id and name in Subgraph AProduct {id: ID!, name: String}N/AN/A
2Extend Product type with id and price in Subgraph BProduct {id: ID!, name: String}Product {id: ID! (external), price: Float}N/A
3Mark @key on id field in both subgraphsProduct @key(fields: "id")Product @key(fields: "id")N/A
4Gateway composes subgraphs, merges Product types by idN/AN/AProduct {id: ID!, name: String, price: Float}
5Query requests Product with name and priceN/AN/AReturns combined fields from both subgraphs
6Execution endsN/AN/AComposition complete, shared type resolved
💡 Composition ends after merging shared types by @key fields and resolving combined schema.
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 4Final
Subgraph A Product Typeundefined{id, name}{id, name}{id, name}{id, name}
Subgraph B Product Typeundefinedundefined{id (external), price}{id (external), price}{id (external), price}
Gateway Composed Product Typeundefinedundefinedundefined{id, name, price}{id, name, price}
Key Moments - 3 Insights
Why do both subgraphs need to mark the shared type with the same @key?
Because the gateway uses the @key field to match and merge the shared types across subgraphs, as shown in execution_table step 3 and 4.
What does the @external directive mean in the extended type?
@external marks fields that exist in another subgraph, so the gateway knows this field is owned elsewhere, as seen in execution_table step 2.
How does the gateway combine fields from both subgraphs into one type?
The gateway merges fields from both subgraphs based on the shared @key, creating a combined type with all fields, as shown in execution_table step 4.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, what fields does the composed Product type have after step 4?
Aid, name
Bid, name, price
Cid, price
Dname, price
💡 Hint
Check the 'Gateway Composition Result' column at step 4 in the execution_table.
At which step does the gateway merge the shared types from subgraphs?
AStep 4
BStep 3
CStep 2
DStep 5
💡 Hint
Look for the step where 'Gateway composes subgraphs' in the execution_table.
If the @key directive was missing in one subgraph, what would happen during composition?
AThe gateway would ignore the subgraph missing @key.
BThe gateway would still merge types correctly.
CThe gateway would fail to merge the shared types properly.
DThe gateway would merge only the fields from the subgraph with @key.
💡 Hint
Refer to key_moments about the importance of matching @key directives.
Concept Snapshot
Shared types across subgraphs use the same type name and @key directive.
Each subgraph defines or extends the type with @external fields.
The gateway composes these types by merging fields based on the @key.
This allows queries to access combined fields from multiple subgraphs.
Missing @key prevents proper merging.
Use @external to mark fields owned by other subgraphs.
Full Transcript
In GraphQL federation, shared types are defined in multiple subgraphs with the same name and marked with the @key directive on a unique field like 'id'. One subgraph defines the base type with some fields, and another subgraph can extend it with additional fields marked as @external if owned elsewhere. The gateway composes these subgraphs by merging the shared types using the @key field to identify matching types. This results in a combined type that includes all fields from the subgraphs. Queries can then request fields from the combined type seamlessly. If the @key directive is missing in any subgraph, the gateway cannot merge the types properly, causing errors or incomplete schemas.

Practice

(1/5)
1. What is the main purpose of using @key in shared types across GraphQL subgraphs?
easy
A. To mark fields that uniquely identify an entity across subgraphs
B. To define a field as optional in the schema
C. To specify the data type of a field
D. To mark a field as deprecated

Solution

  1. Step 1: Understand the role of @key

    The @key directive marks fields that uniquely identify an entity across subgraphs, enabling them to share the same type.
  2. Step 2: Differentiate from other directives

    Other directives like @external or @deprecated serve different purposes, not unique identification.
  3. Final Answer:

    To mark fields that uniquely identify an entity across subgraphs -> Option A
  4. Quick Check:

    @key marks unique identifiers [OK]
Hint: Remember: @key means unique ID for shared types [OK]
Common Mistakes:
  • Confusing @key with @external
  • Thinking @key marks optional fields
  • Assuming @key defines data types
2. Which of the following is the correct way to mark a field as coming from another subgraph in a shared type?
easy
A. Use @key directive on the field
B. Use @provides directive on the field
C. Use @requires directive on the field
D. Use @external directive on the field

Solution

  1. Step 1: Identify the directive for external fields

    The @external directive marks fields that are owned by another subgraph but referenced in the current one.
  2. Step 2: Differentiate from other directives

    @key marks unique identifiers, @requires and @provides relate to field dependencies, not external ownership.
  3. Final Answer:

    Use @external directive on the field -> Option D
  4. Quick Check:

    @external marks fields from other subgraphs [OK]
Hint: External fields use @external directive [OK]
Common Mistakes:
  • Using @key instead of @external
  • Confusing @requires with @external
  • Not marking external fields at all
3. Given the following subgraph schema snippet:
type Product @key(fields: "id") {
  id: ID!
  name: String
  price: Float @external
}

Which statement is true about the price field?
medium
A. It is defined and owned by this subgraph
B. It is a unique identifier for Product
C. It is defined in another subgraph and referenced here
D. It is deprecated and should not be used

Solution

  1. Step 1: Analyze the @external directive on price

    The @external directive means price is not owned here but comes from another subgraph.
  2. Step 2: Understand the role of @key on id

    The id field is the unique identifier, so price is not an ID.
  3. Final Answer:

    It is defined in another subgraph and referenced here -> Option C
  4. Quick Check:

    @external means field is from another subgraph [OK]
Hint: Fields with @external come from other subgraphs [OK]
Common Mistakes:
  • Thinking @external means field is owned here
  • Confusing @key with @external
  • Assuming @external means deprecated
4. Consider this subgraph type definition:
type User @key(fields: "userId") {
  userId: ID!
  email: String @external
  name: String
}

Which statement is true about the email field?
medium
A. It is defined in another subgraph and referenced here
B. The @key directive must include email field
C. The userId field cannot be used as a key
D. The name field must be marked @external

Solution

  1. Step 1: Analyze the @external directive on email

    The @external directive means email is defined in another subgraph and referenced here.
  2. Step 2: Differentiate from other fields

    userId is the @key field provided locally, name is owned locally (no directive).
  3. Final Answer:

    It is defined in another subgraph and referenced here -> Option A
  4. Quick Check:

    @external means field from another subgraph [OK]
Hint: @external means field from another subgraph [OK]
Common Mistakes:
  • Thinking @external means owned locally
  • Believing @key must include all fields
  • Assuming all fields need @external
5. You have two subgraphs sharing a 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?
hard
A. Both subgraphs own isbn, causing a conflict
B. Subgraph A owns isbn and title, Subgraph B extends Book using isbn as key and adds author
C. Subgraph B owns isbn and author, Subgraph A only references isbn
D. Subgraph B cannot extend Book without redefining title

Solution

  1. Step 1: Identify ownership of fields

    Subgraph A defines Book with isbn and title, so it owns these fields.
  2. Step 2: Understand extension in Subgraph B

    Subgraph B extends Book, marking isbn as @external (owned by A) and adds author.
  3. Step 3: Confirm no conflicts

    Using @key with the same field isbn allows both subgraphs to share the type without conflict.
  4. Final Answer:

    Subgraph A owns isbn and title, Subgraph B extends Book using isbn as key and adds author -> Option B
  5. Quick Check:

    Extension uses @external keys to share types [OK]
Hint: Extension uses @external keys to share types [OK]
Common Mistakes:
  • Thinking both subgraphs own the same key field
  • Believing extension requires redefining all fields
  • Assuming conflicts occur with shared keys