Bird
Raised Fist0
GraphQLquery~10 mins

Subgraph definition 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 - Subgraph definition
Start Subgraph Definition
Define Types and Fields
Add @key Directive for Entity
Add @external Directive for Shared Fields
Add @requires or @provides for Field Dependencies
Export Subgraph Schema
Subgraph Ready for Federation
This flow shows how to define a GraphQL subgraph schema step-by-step for federation.
Execution Sample
GraphQL
type Product @key(fields: "id") {
  id: ID!
  name: String
  price: Float
  weight: Float @external
}
Defines a Product type with a key and marks weight as external to indicate it's owned by another subgraph.
Execution Table
StepActionSchema PartDirective AppliedEffect
1Define Product typetype Product { id, name, price, weight }NoneBasic type with fields
2Add @key directivetype Product @key(fields: "id")@key(fields: "id")Marks id as entity key
3Mark weight as externalweight: Float @external@externalIndicates weight is owned by another subgraph
4Complete subgraph schemaFull schema with directivesAll appliedSubgraph ready for federation
💡 All necessary directives applied, subgraph schema is valid and ready
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 3Final
Product TypeundefinedDefined with fieldsAdded @key directiveMarked weight @externalFinal subgraph type definition
DirectivesNoneNone@key(fields: "id")@key + @externalAll directives applied
Key Moments - 3 Insights
Why do we add the @key directive to a type?
The @key directive marks which field(s) uniquely identify an entity across subgraphs, as shown in execution_table step 2.
What does the @external directive mean on a field?
It means the field is owned by another subgraph and is referenced here, as shown in execution_table step 3.
Can a subgraph define a type without any directives?
Yes, but it won't participate in federation properly. Directives like @key are needed for entity resolution, as shown in steps 2 and 3.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, at which step is the @key directive added?
AStep 2
BStep 1
CStep 3
DStep 4
💡 Hint
Refer to the 'Directive Applied' column in execution_table row for Step 2.
According to variable_tracker, what is the state of the Product Type after Step 3?
AAdded @key directive only
BMarked weight @external
CDefined with fields only
DNo directives applied
💡 Hint
Check the 'Product Type' row under 'After Step 3' in variable_tracker.
If we omit the @external directive on weight, what effect would it have?
ASchema becomes invalid
BWeight is ignored in federation
CWeight is treated as owned by this subgraph
DNo effect
💡 Hint
Recall the meaning of @external from key_moments and execution_table step 3.
Concept Snapshot
Subgraph Definition in GraphQL:
- Define types with fields
- Use @key(fields: "id") to mark entity keys
- Use @external on fields owned by other subgraphs
- Optionally use @requires/@provides for dependencies
- Export schema for federation
Full Transcript
Defining a subgraph in GraphQL involves creating types with fields and adding special directives. The @key directive marks the unique identifier for entities, enabling federation to recognize them. The @external directive marks fields that belong to other subgraphs but are referenced here. This process ensures the subgraph schema is ready to be combined with others in a federated graph. The execution table shows each step applying these directives, and the variable tracker shows how the type and directives evolve. Understanding these directives is key to building federated GraphQL services.

Practice

(1/5)
1. What is the main purpose of defining a subgraph in a GraphQL architecture?
easy
A. To split a large graph into smaller, manageable parts
B. To increase the number of queries sent to the server
C. To combine multiple databases into one
D. To replace the need for a schema in GraphQL

Solution

  1. Step 1: Understand the concept of subgraphs

    Subgraphs are used to divide a big graph into smaller parts for clarity and manageability.
  2. Step 2: Identify the main purpose

    The main goal is to make data easier to manage and improve collaboration by splitting the graph.
  3. Final Answer:

    To split a large graph into smaller, manageable parts -> Option A
  4. Quick Check:

    Subgraphs = smaller parts [OK]
Hint: Subgraphs break big graphs into smaller pieces [OK]
Common Mistakes:
  • Thinking subgraphs increase query count
  • Confusing subgraphs with database merging
  • Believing subgraphs replace schemas
2. Which of the following is the correct way to define a unique key for a subgraph entity using the @key directive?
easy
A. type Product @key(fields: id) { id: ID! name: String }
B. type Product @key(id) { id: ID! name: String }
C. type Product @key(fields: "id") { id: ID! name: String }
D. type Product @key("id") { id: ID! name: String }

Solution

  1. Step 1: Recall the syntax of the @key directive

    The @key directive requires the fields argument as a string specifying the unique key fields.
  2. Step 2: Match the correct syntax

    type Product @key(fields: "id") { id: ID! name: String } correctly uses @key(fields: "id") with quotes around the field name.
  3. Final Answer:

    type Product @key(fields: "id") { id: ID! name: String } -> Option C
  4. Quick Check:

    @key(fields: "id") = correct syntax [OK]
Hint: Use quotes around fields in @key directive [OK]
Common Mistakes:
  • Omitting quotes around field names
  • Using @key without 'fields:' keyword
  • Passing field name without string quotes
3. Given this subgraph definition:
type User @key(fields: "userID") {
  userID: ID!
  name: String
  email: String
}

What will happen if you query for { user { userID name } } in a federated setup?
medium
A. The query returns userID and name for the User entity correctly
B. The query fails because email is missing in the query
C. The query returns only userID but not name
D. The query returns an error due to missing @key directive

Solution

  1. Step 1: Understand the @key directive role

    The @key directive marks userID as the unique identifier for User entities in the subgraph.
  2. Step 2: Analyze the query fields

    The query requests userID and name, both defined in the User type, so it will succeed.
  3. Final Answer:

    The query returns userID and name for the User entity correctly -> Option A
  4. Quick Check:

    Query fields in schema = successful fetch [OK]
Hint: Query only requested fields defined in subgraph [OK]
Common Mistakes:
  • Assuming all fields must be queried
  • Confusing @key with required query fields
  • Expecting error if some fields are omitted
4. Consider this subgraph schema:
type Product @key(fields: "sku") {
  sku: ID!
  name: String
  price: Float
}

Which of the following fixes the error in this subgraph definition?

Option A:
type Product @key(fields: "id") {
  sku: ID!
  name: String
  price: Float
}

Option B:
type Product @key(fields: sku) {
  sku: ID!
  name: String
  price: Float
}

Option C:
type Product @key(fields: "sku") {
  sku: ID!
  name: String
  price: Float
}

Option D:
type Product {
  sku: ID!
  name: String
  price: Float
}
medium
A. Change @key fields to "id" instead of "sku"
B. No change needed; the original schema is correct
C. Remove quotes around sku in @key directive
D. Remove the @key directive entirely

Solution

  1. Step 1: Check the original @key syntax

    The original schema uses @key(fields: "sku") correctly with quotes around the field name.
  2. Step 2: Verify field existence

    The field sku exists and matches the @key directive, so no error is present.
  3. Final Answer:

    No change needed; the original schema is correct -> Option B
  4. Quick Check:

    Correct @key syntax and matching field = no error [OK]
Hint: Quotes around fields in @key are required [OK]
Common Mistakes:
  • Removing quotes around fields in @key
  • Using a field name not present in the type
  • Removing @key directive causing federation errors
5. You want to create a subgraph for an Orders service. Each Order has a unique orderID and a list of items. Which is the best way to define the subgraph schema to support federation and ensure uniqueness?
hard
A. type Order @key(fields: "orderID items") { orderID: ID! items: [String] }
B. type Order { orderID: ID! items: [String] }
C. type Order @key(fields: "items") { orderID: ID! items: [String] }
D. type Order @key(fields: "orderID") { orderID: ID! items: [String] }

Solution

  1. Step 1: Identify the unique key for the Order entity

    The unique identifier is orderID, so it should be used in the @key directive.
  2. Step 2: Check the correct @key usage

    Using @key(fields: "orderID") correctly marks orderID as the unique key for federation.
  3. Final Answer:

    type Order @key(fields: "orderID") { orderID: ID! items: [String] } -> Option D
  4. Quick Check:

    Unique key = orderID in @key [OK]
Hint: Use unique ID field in @key directive for subgraph entities [OK]
Common Mistakes:
  • Omitting @key directive causing federation issues
  • Using non-unique fields like items in @key
  • Combining multiple fields incorrectly in @key