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
| Option | Type | Description |
|---|---|---|
keys | string | The field(s) that uniquely identify this entity |
resolvable | bool | Whether this subgraph can resolve the entity |
extend | bool | Whether 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:
- Marked as required - Use
required: true - Non-null in responses - Always return a value
- Consistent across subgraphs - Same type everywhere