Join us from October 8-10 in New York City to learn the latest tips, trends, and news about GraphQL Federation and API platform engineering.Join us for GraphQL Summit 2024 in NYC
Docs
Start for Free

Thinking in Entities

Best practices for designing your schema with entities

federationschema-design

Want to learn about entities in-person?

Don't miss the Federation from day 1: Thinking in entities workshop at this year's GraphQL Summit.

💡 TIP

If you're an enterprise customer looking for more material on this topic, try the Enterprise best practices: Schema design course on .

Not an enterprise customer? Learn about GraphOS for Enterprise.

Entities are the core building blocks of a federated , so the adoption of any schema design best practice must be approached with the unique role of entities in mind. While there's no requirement for to define any entities at all with , the federated schema design process often begins by thinking about what the initial types will be and how they will be referenced and extended throughout the graph to help preserve the separation of concerns between subgraphs both today and as the graph evolves in the future.

Define, reference, and extend entities as needed

The Apollo Federation specification indicates that an Object or Interface type can be made into an entity by adding the @key to its definition in a . The @key directive defines a unique key for the entity and its fields will contain one or more of the type's . In the following example, the Product entity's primary key would be its upc :

Products Subgraph
type Product @key(fields: "upc") {
upc: String!
name: String!
description: String
}

Setting the upc field as the key means that other subgraphs that want to use this entity will need to know at least that value for any product. The keys we define should be values that uniquely identify a resource. This is because we want to avoid scenarios where they are used to arbitrarily pass dynamic field data around execution between subgraphs.

After defining an entity in a schema, other subgraphs can reference that entity in their schemas. In order for the referencing subgraph's schema to be valid, it must define a stub of the entity in its schema. For example, we can reference a Product type defined in the products as the return type corresponding to a product field on a Review type defined in reviews subgraph:

Reviews Subgraph
type Review {
rating: Int
product: Product
}
type Product @key(fields: "upc") {
upc: String!
}

The @key directive indicates that the reviews subgraph will be able to identify a product by its UPC value and therefore be able to connect to a product based on its upc primary key field, but the reviews subgraph does not need to be aware of any other details about a given product.

Referencing entities is a key feature of federation, but it's only half of the story. While an entity will be owned by a single subgraph, other subgraphs might wish to add additional fields to the entity's type to provide a more holistic representation of the entity in the graph. Doing so is a simple as adding the additional field to the extended type in a non-originating subgraph. For example, a reviews subgraph's schema might add a reviews field to the extended Product type that was originally defined in the products subgraph:

Reviews Subgraph
type Review {
rating: Int
product: Product
}
type Product @key(fields: "upc") {
upc: String!
reviews: [Review]
}

When extending entities, it's important to keep in mind that the entity's originating subgraph will not be aware of the added fields. Additionally, each field in an entity must only be defined once or the gateway will encounter schema errors.

Work from the entities outward

When migrating from a client-only or monolithic pattern, that work begins by identifying what entities will be exposed in the first subgraph extracted from the larger schema. When migrating from an architecture consisting of BFF-based GraphQL APIs or any other architecture of multiple overlapping graphs, the work of identifying entities (and determining new subgraph boundaries, in general) might be a bit more complex and involve some degree of negotiation with respect to type ownership, as well as a migration process to help account for any breaking changes that might result for clients.

Whatever your architectural starting point, Apollo Federation was designed to allow the work of identifying entities and defining subgraph boundaries to be done in an incremental, non-disruptive fashion. Beginning to identify these entities is also the essential prerequisite for adopting the other schema design best practices that will follow.

For more information on entity usage and capabilities, please see the Entities documentation page.

@defer and entities

Entities aren't just useful for connecting data across subgraphs. You can also use entities to enable the new @defer directive for client-controlled prioritization of response data. The can defer resolution of fields in entities (and root fields) and handle sending data back to the client in prioritized chunks. By defining types as entities within your graph, clients can improve perceived user experience by adding a directive to their .

Next
Home
Rate articleRateEdit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc., d/b/a Apollo GraphQL.

Privacy Policy

Company