Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Defining Entities

Entities are the building blocks of Apollo Federation. They’re types that can be resolved across multiple subgraphs using a unique key.

Basic Entity Definition

Use the graphql.entity option on your protobuf messages:

message User {
  option (graphql.entity) = {
    keys: "id"
    resolvable: true
  };
  
  string id = 1 [(graphql.field) = { required: true }];
  string name = 2;
  string email = 3 [(graphql.field) = { shareable: true }];
}

Entity Options

OptionTypeDescription
keysstringThe field(s) that uniquely identify this entity
resolvableboolWhether this subgraph can resolve the entity
extendboolWhether this extends an entity from another subgraph

Generated GraphQL

The above proto generates:

type User @key(fields: "id") {
  id: ID!
  name: String
  email: String @shareable
}

Composite Keys

Use space-separated fields for composite keys:

message Product {
  option (graphql.entity) = {
    keys: "sku region"
    resolvable: true
  };
  
  string sku = 1 [(graphql.field) = { required: true }];
  string region = 2 [(graphql.field) = { required: true }];
  string name = 3;
}

Generated:

type Product @key(fields: "sku region") {
  sku: ID!
  region: ID!
  name: String
}

Multiple Keys

Define multiple key sets by repeating the graphql.entity option or using multiple key definitions:

message User {
  option (graphql.entity) = {
    keys: "id"
    resolvable: true
  };
  
  string id = 1;
  string email = 2;  // Could also be a key
}

Resolvable vs Non-Resolvable

Resolvable Entities

When resolvable: true, this subgraph can fully resolve the entity:

message User {
  option (graphql.entity) = {
    keys: "id"
    resolvable: true  // Can resolve User by id
  };
  
  string id = 1;
  string name = 2;
  string email = 3;
}

Stub Entities

When resolvable: false, this subgraph only references the entity:

message User {
  option (graphql.entity) = {
    keys: "id"
    resolvable: false  // Cannot resolve, just references
  };
  
  string id = 1 [(graphql.field) = { external: true }];
}

Real-World Example

Users Service (owns User entity):

message User {
  option (graphql.entity) = {
    keys: "id"
    resolvable: true
  };
  
  string id = 1 [(graphql.field) = { required: true }];
  string name = 2 [(graphql.field) = { shareable: true }];
  string email = 3 [(graphql.field) = { shareable: true }];
}

Reviews Service (references User):

message Review {
  string id = 1;
  string body = 2;
  User author = 3;  // Reference to User from Users service
}

message User {
  option (graphql.entity) = {
    keys: "id"
    extend: true  // Extending User from another subgraph
  };
  
  string id = 1 [(graphql.field) = { external: true, required: true }];
  repeated Review reviews = 2 [(graphql.field) = { requires: "id" }];
}

Key Field Requirements

Key fields should be:

  1. Marked as required - Use required: true
  2. Non-null in responses - Always return a value
  3. Consistent across subgraphs - Same type everywhere