@@ -840,7 +840,7 @@ Federation Library: Apo
Plugin based GraphQL schema builder that makes building graphql schemas with TypeScript easy, fast and enjoyable.
-Github: hayes/pothos
+GitHub: hayes/pothos
Type: Code first
Stars: 2.2k β
@@ -897,7 +897,7 @@ Core Library: GraphQL.js
A framework for serving GraphQL from Laravel
-Github: nuwave/lighthouse
+GitHub: nuwave/lighthouse
Type: SDL first
Stars: 3.3k β
@@ -940,7 +940,7 @@ Core Library: webonyx/graphql-p
|
PHP implementation of the GraphQL specification based on the reference implementation in JavaScript
-Github: webonyx/graphql-php
+GitHub: webonyx/graphql-php
Type: Code first
Stars: 4.6k β
@@ -997,7 +997,7 @@ Federation Library: mirumee/ariadne
+GitHub: mirumee/ariadne
Type: SDL first
Stars: 2.1k β
@@ -1040,7 +1040,7 @@ Core Library: GraphQL-c
|
GraphQL framework for Python
-Github: graphql-python/graphene
+GitHub: graphql-python/graphene
Type: Code first
Stars: 8.0k β
@@ -1084,7 +1084,7 @@ Federation Library: strawberry-graphql/strawberry
+GitHub: strawberry-graphql/strawberry
Type: Code first
Stars: 3.8k β
@@ -1141,7 +1141,7 @@ Core Library: GraphQL-c
|
Ruby implementation of GraphQL
-Github: rmosolgo/graphql-ruby
+GitHub: rmosolgo/graphql-ruby
Type: Code first
Stars: 5.3k β
@@ -1198,7 +1198,7 @@ Federation Library: G
|
A GraphQL server library implemented in Rust
-Github: async-graphql/async-graphql
+GitHub: async-graphql/async-graphql
Type: Code first
Stars: 3.2k β
@@ -1254,7 +1254,7 @@ Last Release: 2022-11-28
|
Functional GraphQL library for Scala
-Github: ghostdogpr/caliban
+GitHub: ghostdogpr/caliban
Type: Code first
Stars: 939 β
@@ -1296,7 +1296,7 @@ Last Release: 2024-04-16
|
Scala GraphQL implementation
-Github: sangria-graphql/sangria
+GitHub: sangria-graphql/sangria
Type: Code first
Stars: 2.0k β
@@ -1353,7 +1353,7 @@ Federation Library: GraphQLSwift/Graphiti
+GitHub: GraphQLSwift/Graphiti
Type: SDL first
Stars: 523 β
@@ -1483,7 +1483,7 @@ Last Release: 2023-11-15
|
The GraphQL platform
-Github: grafbase/grafbase
+GitHub: grafbase/grafbase
Type: Code first | SDL first
Stars: 934 β
@@ -1525,7 +1525,7 @@ Last Release: 2024-02-23
|
Executable GraphQL schema from multiple data sources, query anything, run anywhere.
-Github: Urigo/graphql-mesh
+GitHub: Urigo/graphql-mesh
Stars: 3.2k β
@@ -1567,14 +1567,14 @@ Last Release: 2024-04-30
|
A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations.
-Github: neo4j/graphql
+GitHub: neo4j/graphql
Type: Code first | SDL first
Stars: 485 β
Last Release: 2024-04-30
Core Library: GraphQL.js
-Federation Library: Apollo Subgraph
+Federation Library: Apollo Subgraph
|
diff --git a/docs/source/reference/federation/composition-rules.mdx b/docs/source/reference/federation/composition-rules.mdx
new file mode 100644
index 000000000..9d852077a
--- /dev/null
+++ b/docs/source/reference/federation/composition-rules.mdx
@@ -0,0 +1,470 @@
+---
+title: Composition Rules
+subtitle: Learn what rules subgraph schemas must follow to successfully compose
+description: Learn what rules subgraph schemas must follow to successfully compose in a federated GraphQL architecture.
+redirectFrom:
+ - /federation/federated-types/composition/#rules-of-composition
+ - /federation/federated-schemas/composition/#rules-of-composition
+---
+
+In Federation 2, your subgraph schemas must follow all of these rules to successfully compose into a supergraph schema:
+
+- Multiple subgraphs can't define the same field on an object type, unless that field is [shareable](/graphos/schema-design/federated-schemas/sharing-types#using-shareable).
+- A shared field must have both a compatible return type and compatible argument types across each defining subgraph.
+ - For examples of compatible and incompatible differences between subgraphs, see [Differing shared fields](/graphos/schema-design/federated-schemas/sharing-types#differing-shared-fields).
+- If multiple subgraphs define the same type, each field of that type must be resolvable by every valid GraphQL operation that includes it.
+ - This rule is the most complex and the most essential to Federation 2. [Let's look at it more closely.](#unresolvable-field-example)
+
+### Unresolvable field example
+
+This example presents a field of a shared type that is not always resolvable (and therefore [breaks composition](#breaking-composition)).
+
+Consider these subgraph schemas:
+
+β
+
+
+
+```graphql title="Subgraph A"
+type Query {
+ positionA: Position!
+}
+
+type Position @shareable {
+ x: Int!
+ y: Int!
+}
+```
+
+```graphql title="Subgraph B"
+type Query {
+ positionB: Position!
+}
+
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int!
+}
+```
+
+
+
+
+Note the following about these two subgraphs:
+
+- They both define a shared `Position` type.
+- They both define a top-level `Query` field that returns a `Position`.
+- Subgraph B's `Position` includes a `z` field, whereas Subgraph A's definition only includes shared `x` and `y` fields.
+
+Individually, these subgraph schemas are perfectly valid. However, if they're combined, they break composition. Why?
+
+The composition process attempts to merge inconsistent type definitions into a single definition for the supergraph schema. In this case, the resulting definition for `Position` exactly matches Subgraph B's definition:
+
+β
+
+```graphql title="Hypothetical supergraph schema"
+type Query {
+ # From A
+ positionA: Position!
+ # From B
+ positionB: Position!
+}
+
+type Position {
+ # From A+B
+ x: Int!
+ y: Int!
+ # From B
+ z: Int!
+}
+```
+
+Based on this hypothetical supergraph schema, the following query should be valid:
+
+```graphql {5}
+query GetPosition {
+ positionA {
+ x
+ y
+ z # β οΈ Can't be resolved! β οΈ
+ }
+}
+```
+
+Here's our problem. Only Subgraph A can resolve `Query.positionA`, because Subgraph B doesn't define the field. But Subgraph A doesn't define `Position.z`!
+
+If the router sent this query to Subgraph A, it would return an error. And without extra configuration, Subgraph B can't resolve a `z` value for a `Position` in Subgraph A. Therefore, `Position.z` is unresolvable for this query.
+
+Composition recognizes this potential issue, and it fails. The hypothetical supergraph schema above would never actually be generated.
+
+`Position.z` is an example of a field that is not always resolvable. Refer to the following section for solutions.
+
+### Solutions for unresolvable fields
+
+There are multiple solutions for making sure that a field of a shared type is always resolvable. Choose a solution based on your use case:
+
+#### Define the field in every subgraph that defines the type
+
+If every subgraph that defines a type could resolve every field of that type without introducing complexity, a straightforward solution is to define and resolve all fields in all of those subgraphs:
+
+β
+
+
+
+```graphql {4} title="Subgraph A"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int
+}
+```
+
+```graphql title="Subgraph B"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int!
+}
+```
+
+
+
+In this case, if Subgraph A only cares about the `x` and `y` fields, its resolver for `z` can always return `null`.
+
+This is a useful solution for shared types that encapsulate simple scalar data.
+
+
+
+You can use the `@inaccessible` directive to incrementally add a value type field to multiple subgraphs without breaking composition. [Learn more.](/graphos/schema-design/federated-schemas/sharing-types#adding-new-shared-fields)
+
+
+
+#### Make the shared type an entity
+
+β
+
+
+
+```graphql title="Subgraph A"
+type User @key(fields: "id") {
+ id: ID!
+ name: String!
+}
+```
+
+```graphql title="Subgraph B"
+type User @key(fields: "id") {
+ id: ID!
+ age: Int!
+}
+```
+
+
+
+If you make a shared type an [entity](/graphos/schema-design/federated-schemas/entities/intro), different subgraphs can define any number of different fields for that type, as long as they all define key fields for it.
+
+This is a useful solution when a type corresponds closely to an entry in a data store that one or more of your subgraphs has access to (for example, a `Users` database).
+
+## Merging types from multiple subgraphs
+
+If a particular GraphQL type is defined differently by different subgraphs, composition uses one of two strategies to merge those definitions: _union_ or _intersection_.
+
+- **Union**: The supergraph schema includes all parts of all subgraph definitions for the type.
+- **Intersection**: The supergraph schema includes only the parts of the type that are present in every subgraph that defines the type.
+
+The merging strategy that composition uses for a particular type depends on the type, as described below.
+
+### Object, union, and interface types
+
+Composition always uses the union strategy to merge object, union, and interface types.
+
+Consider the following subgraph schemas:
+
+
+
+```graphql title="Subgraph A"
+type User @key(fields: "id") {
+ id: ID!
+ name: String!
+ email: String!
+}
+
+union Media = Book | Movie
+
+interface BookDetails {
+ title: String!
+ author: String!
+}
+```
+
+```graphql title="Subgraph B"
+type User @key(fields: "id") {
+ id: ID!
+ age: Int!
+}
+
+union Media = Book | Podcast
+
+interface BookDetails {
+ title: String!
+ numPages: Int
+}
+```
+
+
+
+When these subgraph schemas are composed, the composition process merges the three corresponding types by union. This results in the following type definitions in the supergraph schema:
+
+```graphql title="Supergraph schema"
+type User {
+ id: ID!
+ age: Int!
+ name: String!
+ email: String!
+}
+
+union Media = Book | Movie | Podcast
+
+interface BookDetails {
+ title: String!
+ author: String!
+ numPages: Int
+}
+```
+
+Because composition uses the union strategy for these types, subgraphs can contribute distinct parts and guarantee that those parts will appear in the composed supergraph schema.
+
+
+
+If different subgraphs contribute different fields to an interface type, any object types that implement that interface must define all contributed fields from all subgraphs. Otherwise, composition fails.
+
+
+
+### Input types and field arguments
+
+Composition always uses the intersection strategy to merge input types and field arguments. This ensures that the router never passes an argument to a subgraph that doesn't define that argument.
+
+Consider the following subgraph schemas:
+
+
+
+```graphql title="Subgraph A"
+input UserInput {
+ name: String!
+ age: Int
+}
+
+type Library @shareable {
+ book(title: String, author: String): Book
+}
+```
+
+```graphql title="Subgraph B"
+input UserInput {
+ name: String!
+ email: String
+}
+
+type Library @shareable {
+ book(title: String, section: String): Book
+}
+```
+
+
+
+These subgraphs define different fields for the `UserInput` input type, and they define different arguments for the `Library.book` field. After composition merges using intersection, the supergraph schema definitions look like this:
+
+```graphql title="Supergraph schema"
+input UserInput {
+ name: String!
+}
+
+type Library {
+ book(title: String): Book
+}
+```
+
+As you can see, the supergraph schema includes only the input fields and arguments that both subgraphs define.
+
+
+
+If the intersection strategy would omit an input field or argument that is non-nullable, composition fails. This is because at least one subgraph requires that field or argument, and the router can't provide it if it's omitted from the supergraph schema.
+
+When defining input types and field arguments in multiple subgraphs, make sure that every non-nullable field and argument is consistent in every subgraph. For examples, see [Arguments](/graphos/schema-design/federated-schemas/sharing-types#arguments).
+
+
+
+### Enums
+
+If an enum definition differs between subgraphs, the [composition strategy](#merging-types-from-multiple-subgraphs) depends on how the enum is used:
+
+| Scenario | Strategy |
+|----------|----------|
+| The enum is used as the return type for at least one object or interface field. | [Union](#union) |
+| The enum is used as the type for at least one field argument or input type field. | [Intersection](#intersection) |
+| Both of the above are true. | All definitions must [match exactly](#exact-match) |
+
+Examples of these scenarios are provided below.
+
+#### Enum composition examples
+
+##### Union
+
+Consider these subgraph schemas:
+
+
+
+```graphql title="Subgraph A"
+enum Color {
+ RED
+ GREEN
+ BLUE
+}
+
+type Query {
+ favoriteColor: Color
+}
+```
+
+```graphql title="Subgraph B"
+enum Color {
+ RED
+ GREEN
+ YELLOW
+}
+
+type Query {
+ currentColor: Color
+}
+```
+
+
+
+In this case, the `Color` enum is used as the return type of at least one object field. Therefore, composition merges the `Color` enum by union, so that all possible subgraph return values are valid.
+
+This results in the following type definition in the supergraph schema:
+
+```graphql title="Supergraph schema"
+enum Color {
+ RED
+ GREEN
+ BLUE
+ YELLOW
+}
+```
+
+##### Intersection
+
+Consider these subgraph schemas:
+
+
+
+```graphql title="Subgraph A"
+enum Color {
+ RED
+ GREEN
+ BLUE
+}
+
+type Query {
+ products(color: Color): [Product]
+}
+```
+
+```graphql title="Subgraph B"
+enum Color {
+ RED
+ GREEN
+ YELLOW
+}
+
+type Query {
+ images(color: Color): [Image]
+}
+```
+
+
+
+In this case, the `Color` enum is used as the type of at least one field argument (or input type field). Therefore, composition merges the `Color` enum by intersection, so that subgraphs never receive a client-provided enum value that they don't support.
+
+This results in the following type definition in the supergraph schema:
+
+```graphql title="Supergraph schema"
+# BLUE and YELLOW are removed via intersection
+enum Color {
+ RED
+ GREEN
+}
+```
+
+##### Exact match
+
+Consider these subgraph schemas:
+
+β
+
+
+
+```graphql title="Subgraph A"
+enum Color {
+ RED
+ GREEN
+ BLUE
+}
+
+type Query {
+ favoriteColor: Color
+}
+```
+
+```graphql title="Subgraph B"
+enum Color {
+ RED
+ GREEN
+ YELLOW
+}
+
+type Query {
+ images(color: Color): [Image]
+}
+```
+
+
+
+In this case, the `Color` enum is used as both:
+
+- The return type of at least one object field
+- The type of at least one field argument (or input type field)
+
+Therefore, the definition of the `Color` enum must match exactly in every subgraph that defines it. An exact match is the only scenario that enables union and intersection to produce the same result.
+
+The subgraph schemas above do not compose, because their definitions of the `Color` enum differ.
+
+## Directives
+
+Composition handles a directive differently depending on whether it's an "executable" directive or a "type system" directive.
+
+### Executable directives
+
+Executable directives are intended to be used by clients in their queries. They are applied to one or more of the [executable directive locations](http://spec.graphql.org/June2018/#ExecutableDirectiveLocation). For example, you might have a directive definition of `directive @lowercase on FIELD`, which a client could use in their query like so:
+
+```graphql
+query {
+ getSomeData {
+ someField @lowercase
+ }
+}
+```
+
+An executable directive is composed into the supergraph schema only if all of the following conditions are met:
+
+- The directive is defined in all subgraphs.
+- The directive is defined identically in all subgraphs.
+- The directive is not included in any [`@composeDirective`](/graphos/reference/federation/directives#composedirective) directives.
+
+### Type system directives
+
+Type system directives help define the structure of the schema and are not intended for use by clients. They are applied to one or more of the [type system directive locations](http://spec.graphql.org/June2018/#TypeSystemDirectiveLocation).
+
+These directives are not composed into the supergraph schema, but they can still provide information to the router via the [`@composeDirective`](/graphos/reference/federation/directives#composedirective) directive.
diff --git a/docs/source/federated-schemas/federated-directives.mdx b/docs/source/reference/federation/directives.mdx
similarity index 99%
rename from docs/source/federated-schemas/federated-directives.mdx
rename to docs/source/reference/federation/directives.mdx
index 763eabe69..8ad0733bc 100644
--- a/docs/source/federated-schemas/federated-directives.mdx
+++ b/docs/source/reference/federation/directives.mdx
@@ -4,8 +4,8 @@ subtitle: Reference for Apollo Federation specific GraphQL directives
description: Reference for GraphQL federation directives including @key, @extends, @sharable, @override, @requires and more.
---
-import ProgressiveOverrideEnterprise from '../../shared/progressive-override-enterprise.mdx';
-import EnterpriseDirective from '../../shared/enterprise-directive.mdx';
+import ProgressiveOverrideEnterprise from '../../../shared/progressive-override-enterprise.mdx';
+import EnterpriseDirective from '../../../shared/enterprise-directive.mdx';
Apollo Federation defines a collection of directives that you use in your subgraph schemas to enable certain features.
diff --git a/docs/source/errors.mdx b/docs/source/reference/federation/errors.mdx
similarity index 100%
rename from docs/source/errors.mdx
rename to docs/source/reference/federation/errors.mdx
diff --git a/docs/source/hints.mdx b/docs/source/reference/federation/hints.mdx
similarity index 100%
rename from docs/source/hints.mdx
rename to docs/source/reference/federation/hints.mdx
diff --git a/docs/source/building-supergraphs/jetbrains-ide-support.mdx b/docs/source/reference/federation/jetbrains-ide-support.mdx
similarity index 96%
rename from docs/source/building-supergraphs/jetbrains-ide-support.mdx
rename to docs/source/reference/federation/jetbrains-ide-support.mdx
index f6c306c18..2fa9f5d4b 100644
--- a/docs/source/building-supergraphs/jetbrains-ide-support.mdx
+++ b/docs/source/reference/federation/jetbrains-ide-support.mdx
@@ -18,7 +18,7 @@ To enable federation support, do the following in your IDE after installing the
diff --git a/docs/source/query-plans.mdx b/docs/source/reference/federation/query-plans.mdx
similarity index 100%
rename from docs/source/query-plans.mdx
rename to docs/source/reference/federation/query-plans.mdx
diff --git a/docs/source/subgraph-spec.mdx b/docs/source/reference/federation/subgraph-spec.mdx
similarity index 100%
rename from docs/source/subgraph-spec.mdx
rename to docs/source/reference/federation/subgraph-spec.mdx
diff --git a/docs/source/building-supergraphs/subgraph-specific-fields.mdx b/docs/source/reference/federation/subgraph-specific-fields.mdx
similarity index 100%
rename from docs/source/building-supergraphs/subgraph-specific-fields.mdx
rename to docs/source/reference/federation/subgraph-specific-fields.mdx
diff --git a/docs/source/federation-versions.mdx b/docs/source/reference/federation/versions.mdx
similarity index 100%
rename from docs/source/federation-versions.mdx
rename to docs/source/reference/federation/versions.mdx
diff --git a/docs/source/federation-2/backward-compatibility.mdx b/docs/source/reference/migration/backward-compatibility.mdx
similarity index 100%
rename from docs/source/federation-2/backward-compatibility.mdx
rename to docs/source/reference/migration/backward-compatibility.mdx
diff --git a/docs/source/reference/migration/from-monolith.mdx b/docs/source/reference/migration/from-monolith.mdx
new file mode 100644
index 000000000..d82b12b74
--- /dev/null
+++ b/docs/source/reference/migration/from-monolith.mdx
@@ -0,0 +1,281 @@
+---
+title: Moving a GraphQL Monolith to Apollo Federation
+subtitle: Steps for migrating from a GraphQL monolith to a federated supergraph
+description: A step-by-step guide for migrating from a GraphQL monolith to a federated supergraph with Apollo Federation.
+published: 2022-09-06
+id: TN0013
+tags: [federation, server]
+redirectFrom:
+ - /technotes/TN0013-monolith-to-federation/
+---
+
+
+
+For a complete, step-by-step tutorial, check out [Voyage II: Federating the monolith](https://www.apollographql.com/tutorials/voyage-part2).
+
+
+
+As with any monolithic service, teams can struggle to change and maintain their GraphQL API as it grows larger and receives contributions from more developers.
+
+Breaking up the monolith into smaller GraphQL APIs might be the right strategy for your team. With Apollo Federation, you can break up a monolith without sacrificing the unified API that your client applications depend on. Each _subgraph_ can be independently updated, deployed, and scaled while contributing to a single unified schema.
+
+Here are the steps we recommend to convert a monolithic GraphQL API into a federated GraphQL API.
+
+## Planning and preparation
+
+### 1. Put a router in front of your existing API
+
+Start the process by making a "federated graph of one." Your existing monolith can act as a subgraph without any schema changes.
+
+1. If you're not already publishing your schema to GraphOS Studio, create a new graph in your Studio organization. Choose "Supergraph" for your graph architecture.
+1. Publish your monolith schema to GraphOS Studio as a subgraph with the following command (modify your `--routing-url` and `--schema` path as needed):
+
+ ```sh
+ rover subgraph publish --name monolith \
+ --schema ./schema.graphql \
+ --routing-url http://monolith.prod.svc.cluster.local/graphql \
+ --convert # necessary if you're publishing to an existing variant
+ ```
+
+1. Deploy an instance of the GraphOS Router to your environment.
+
+
+ Self-hosting the GraphOS Router is limited to [GraphOS Enterprise plans](https://www.apollographql.com/pricing). Other plan types use [managed cloud routing with GraphOS](/graphos/cloud-routing). Check out the [pricing page](https://www.apollographql.com/pricing/) to learn more.
+
+
+1. Set up [header propagation](/router/configuration/header-propagation/) so that the monolith receives any necessary headers from the router.
+1. Set up internal routing rules to redirect client requests to the router instead of your monolith.
+1. Enable usage metrics reporting to GraphOS Studio.
+1. Add [subgraph checks](/graphos/platform/schema-management/checks/) to your monolith's CI pipeline.
+
+At this point, client requests go to your new router instead of the monolith, but it's serving the same schema so clients won't know the difference.
+
+Not only are you prepared to federate your schema, you now have field-level visibility into graph usage and breaking change detection.
+
+### 2. Identify entities
+
+Next, look through all the types in your schema and identify possible [entities](/graphos/schema-design/federated-schemas/entities/intro#entity-overview). Entities are types that form the foundation of your data model, and they must include fields that can uniquely identify each instance of them.
+
+Consider this schema for a travel booking site:
+
+
+
+```graphql
+type Account {
+ id: ID!
+ username: String
+ user: User
+ profile: Profile
+}
+
+type Address {
+ line1: String
+ line2: String
+ city: String
+ state: String
+ zip: String
+}
+
+type Airline {
+ id: ID!
+ name: String
+}
+
+type Airplane {
+ id: ID!
+ class: String
+}
+
+type Airport {
+ code: AirportCode!
+ airlines: [Airline]
+}
+
+type Amenity {
+ name: String
+ description: String
+ photoUrl: String
+}
+
+type Bed {
+ id: ID!
+ size: BedSize
+ room: Room
+}
+
+type CancellationPolicy {
+ text: String
+ updatedAt: DateTime
+}
+
+type Flight {
+ number: FlightNumber!
+ airplane: Airplane
+ origin: Airport
+ destination: Airport
+ scheduledTakeoff: DateTime
+}
+
+type Hotel {
+ id: ID!
+ name: String
+ address: Address
+}
+
+type Profile {
+ name: String
+ address: Address
+ phone: String
+ email: String
+}
+
+type Reservation {
+ account: Account
+ flights: [Flight]
+ hotels: [Hotel]
+}
+
+type Room {
+ number: ID!
+ floor: Int
+ hotel: Hotel
+}
+
+type Seat {
+ number: ID!
+ airplane: Airplane
+}
+
+type User {
+ id: ID!
+ account: Account
+ username: String
+ reservations: [Reservation]
+}
+
+type Query {
+ me: User
+ searchHotels(input: SearchHotelInput!): [Hotel]
+ searchFlights(input: SearchFlightInput!): [Flight]
+}
+```
+
+
+
+Types such as `User`, `Reservation`, `Flight`, and `Hotel` are uniquely identifiable, whereas `Profile`, ` CancellationPolicy`, and `Amenity` are basically groups of attributes attached to those entities.
+
+### 3. Group entities
+
+After you've identified your entities, group them by their logical domain or concern. These groups usually correspond to product boundaries, but they might also be team boundaries. This is how you'll determine how many subgraphs you'll end up with.
+
+| Accounts domain | Flights domain | Hotels domain |
+| --------------- | -------------- | ------------- |
+| `Account` | `Airplane` | `Bed` |
+| `User` | `Airline` | `Hotel` |
+| | `Flight` | `Reservation` |
+| | `Reservation` | `Room` |
+| | `Seat` | |
+
+### 4. Rank entities by ease of migration
+
+When you're deciding how to start migrating types to other subgraphs, it's helpful to consider a few things first:
+
+#### How many related types will you have to migrate at the same time?
+
+Count the number of value types associated with an entity. You'll need to copy all those types over to the new subgraph when you migrate the entity. Entities with fewer related scalars, enums, and non-entity object types will be a bit easier to migrate.
+
+You won't need to move related entities at the same time as long as you can return an [entity reference](/graphos/schema-design/federated-schemas/entities/contribute-fields#referencing-an-entity-without-contributing-fields). For example, you can move the `Room` type if you have access to the `Hotel` foreign key:
+
+```graphql title="Hotels subgraph"
+type Room @key(fields: "number") {
+ number: ID!
+ floor: Int
+ hotel: Hotel
+}
+
+type Hotel @key(fields: "id", resolvable: false) {
+ id: ID! # comes from rooms.hotel_id in the database
+}
+```
+
+It might be safer and easier to move the entire `Room` type but only a "stub" of the `Hotel` type. The query planner can fetch the rest of the `Hotel` fields from the monolith until you move that type as well.
+
+#### How complex will your query plans become during the migration?
+
+If you start by moving a type that's deeply interconnected with other types, you might introduce unnecessary complexity to your router's query plans. For example, consider this query:
+
+```graphql
+query MyFlights {
+ me {
+ reservations {
+ flights {
+ ...FlightDetails
+ }
+ }
+ }
+}
+```
+
+This query returns a list of `Reservation` objects belonging to a particular `User`, and each `Reservation` contains a list of `Flight`s. If you start by moving the `Reservation` type to another subgraph, this query results in an "AβBβA" query plan (fetching the `User`, then the `Reservation`, then the `Flight` in three serial subgraph fetches):
+
+```mermaid
+flowchart TD
+ A(monolith) --> B(subgraph)
+ B --> C(monolith)
+```
+
+A better choice at this stage might be to move the `Flight` type so that the query plan is much more efficient, fetching both the `User` and `Reservation` together before fetching the `Flight`:
+
+```mermaid
+flowchart TD
+ A(monolith) --> B(subgraph)
+```
+
+When you move a type to another subgraph, you should also move all root-level fields that return that type (such as `Query.flight(id:)`. This way, objects of that type can be returned with only a single subgraph operation in the best case. And in the general case, the query plan can fetch any additional data with fewer total subgraph operations:
+
+```mermaid
+flowchart TD
+ A(subgraph) --> B(monolith)
+```
+
+Inevitably, some query plans become more complex while you're migrating types between subgraphs. By ranking your entities and moving the lowest-impact ones first, you can minimize this increase.
+
+## Implementation
+
+### 1. Make your monolith a real subgraph
+
+Now that you have a migration plan, you can start making schema and code changes. The first change is to add the [Apollo Federation subgraph specification](/federation/subgraph-spec/) to the monolith. The steps involved depend on which [Apollo-Federation-compatible library](/graphos/reference/federation/compatible-subgraphs) you use with your monolith's language and framework.
+
+The most important functionality to add is defining your entities (by adding `@key` directives) and adding their [reference resolvers](/graphos/schema-design/federated-schemas/entities/intro#defining-an-entity).
+
+### 2. Deploy your new subgraph
+
+Start with an empty subgraph to quickly set up your deployment and continuous integration pipelines. You can use this stub subgraph schema, which won't affect the client-facing schema:
+
+```graphql
+extend schema @link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@shareable", "@inaccessible"])
+
+type Query {
+ _todo: String @shareable @inaccessible
+}
+```
+
+After your new subgraph is deployed, set up [schema checks and publishes](/rover/commands/subgraphs#publishing-a-subgraph-schema-to-graphos) so that you can catch composition errors quickly and start contributing to the supergraph.
+
+### 3. Move an entity along with related types and relevant root fields
+
+1. Start by marking all the value types (enums and non-entity object types) you're going to move to the subgraph as `@shareable` in the monolith.
+2. Copy the types and fields over to the subgraph schema and port their resolvers from the monolith.
+3. Deploy the subgraph and test it by making calls to it directly. Use the [`_entities` root field](/federation/building-supergraphs/subgraphs-overview/#query_entities) to test joins between entities.
+
+When you're satisfied with the behavior and performance of your new subgraph, you can start moving all traffic to it and cleaning up the monolith.
+
+1. Use the [`@override`](/graphos/reference/federation/directives/#override) directive to mark fields in the subgraph with `@override(from: "monolith")`, telling the query planner to prefer the new subgraph over the monolith.
+2. Remove types and fields from the monolith schema.
+3. Delete unneeded resolvers from the monolith.
+4. Remove `@override` directives from the subgraph.
+5. Remove `@shareable` from types and fields in the subgraph when appropriate.
+
+### 4. Migrate additional functionality out of the monolith as desired
+
+Towards the end of the migration, you can decide whether to leave the monolith in place to handle the few entities that sit in the middle of your domain (such as `User`), or completely deconstruct the monolith into new services and decommission it. Either way, your newly federated GraphQL API is well-positioned to scale even larger in the future.
diff --git a/docs/source/migrating-from-stitching.mdx b/docs/source/reference/migration/migrating-from-stitching.mdx
similarity index 100%
rename from docs/source/migrating-from-stitching.mdx
rename to docs/source/reference/migration/migrating-from-stitching.mdx
diff --git a/docs/source/federation-2/moving-to-federation-2.mdx b/docs/source/reference/migration/moving-to-federation-2.mdx
similarity index 99%
rename from docs/source/federation-2/moving-to-federation-2.mdx
rename to docs/source/reference/migration/moving-to-federation-2.mdx
index 42f0cc7ff..0875a417b 100644
--- a/docs/source/federation-2/moving-to-federation-2.mdx
+++ b/docs/source/reference/migration/moving-to-federation-2.mdx
@@ -88,13 +88,13 @@ Open the Settings page for the variant you want to move to Federation 2, then se
Click **Edit Configuration**. The following dialog appears:
-
+
In the Federation Version dropdown, select **Federation 2** and click **Save**.
diff --git a/docs/source/schema-design/federated-schemas/composition.mdx b/docs/source/schema-design/federated-schemas/composition.mdx
new file mode 100644
index 000000000..112bd7614
--- /dev/null
+++ b/docs/source/schema-design/federated-schemas/composition.mdx
@@ -0,0 +1,104 @@
+---
+title: Schema Composition
+subtitle: Learn how GraphOS combines subgraph schemas into a supergraph schema
+description: Learn about schema composition in a federated GraphQL architecture. Explore strategies for handling conflicting types and directives.
+redirectFrom:
+ - /federation/federated-types/composition
+ - /federation/federated-schemas/composition
+---
+
+In Apollo Federation, _composition_ is the process of combining a set of subgraph schemas into a supergraph schema:
+
+```mermaid
+graph TB;
+ serviceA[Subgraph schema A];
+ serviceB[Subgraph schema B];
+ serviceC[Subgraph schema C];
+ composition[["π Composition "]];
+ supergraph{{"Supergraph schema (A + B + C + routing machinery)"}};
+ serviceA & serviceB & serviceC --> composition;
+ composition -- "(Composition succeeds)" --> supergraph;
+ class composition tertiary;
+```
+
+The supergraph schema includes all of the type and field definitions from your subgraph schemas. It also includes metadata that enables your router to intelligently route incoming GraphQL operations across all of your different subgraphs.
+
+## Supported methods
+
+You can perform schema composition with any of the following methods:
+
+### Automatically with GraphOS
+
+Apollo GraphOS performs composition automatically whenever you publish a subgraph schema.
+This enables your running router to dynamically fetch an updated supergraph schema from Apollo as soon as it's available:
+
+```mermaid
+graph LR;
+ subgraph "Your infrastructure"
+ serviceA[Products subgraph];
+ serviceB[Reviews subgraph];
+ gateway([Router]);
+ end
+ subgraph "GraphOS"
+ registry{{Schema Registry}};
+ uplink{{Apollo Uplink}}
+ end
+ serviceA & serviceB -->|Publishes schema| registry;
+ registry -->|Updates config| uplink;
+ gateway -->|Polls for config changes| uplink;
+ class registry secondary;
+ class uplink secondary;
+```
+
+
+
+GraphOS also provides a [schema linter](/graphos/platform/schema-management/linting) with [composition specific rules](/graphos/platform/schema-management/linting/rules#composition-rules) to help you follow best practices. You can set up schema checks for your graph in GraphOS Studio or perform one-off linting with the Rover CLI. Check out the [schema linting](/graphos/platform/schema-management/linting) docs to learn more.
+
+
+
+### Manually with the Rover CLI
+
+The [Rover CLI](https://www.apollographql.com/docs/rover/) supports a `supergraph compose` command that you can use to compose a supergraph schema from a collection of subgraph schemas:
+
+```bash showLineNumbers=false
+rover supergraph compose --config ./supergraph-config.yaml
+```
+
+To learn how to install Rover and use this command, see the [Rover docs](/rover/).
+
+## Breaking composition
+
+Sometimes, your subgraph schemas might conflict in a way that causes composition to fail. This is called _breaking composition_.
+
+For example, take a look at these two subgraph schemas:
+
+β
+
+
+```graphql {2} title="Subgraph A"
+type Event @shareable {
+ timestamp: String!
+}
+```
+
+```graphql {2} title="Subgraph B"
+type Event @shareable {
+ timestamp: Int!
+}
+```
+
+
+
+One subgraph defines `Event.timestamp` as a `String`, and the other defines it as an `Int`. Composition doesn't know which type to use, so it fails.
+
+
+
+For examples of valid inconsistencies in field return types, see [Differing shared field return types](/graphos/schema-design/federated-schemas/sharing-types/#return-types).
+
+
+
+Breaking composition is a helpful feature of federation! Whenever a team modifies their subgraph schema, those changes might conflict with another subgraph. But that conflict won't affect your router, because composition fails to generate a new supergraph schema. It's like a compiler error that prevents you from running invalid code. Refer to the [Composition Rules Reference](/graphos/reference/federation/composition-rules) for details.
+
+## Next steps
+
+Ready to compose your first supergraph? [Get started with GraphOS!](/graphos/get-started/guides/quickstart)
diff --git a/docs/source/schema-design/federated-schemas/entities/best-practices.mdx b/docs/source/schema-design/federated-schemas/entities/best-practices.mdx
new file mode 100644
index 000000000..e00b7a61c
--- /dev/null
+++ b/docs/source/schema-design/federated-schemas/entities/best-practices.mdx
@@ -0,0 +1,84 @@
+---
+title: Thinking in Entities
+subtitle: Best practices for designing your schema with entities
+description: Schema design best practices for entities, including when to define, reference and extend entities.
+published: 2023-01-09
+id: TN0026
+tags: [federation, schema-design]
+redirectFrom:
+ - /technotes/TN0026-thinking-in-entities/
+---
+
+
+
+If you're an enterprise customer looking for more material on this topic, try the [Enterprise best practices: Schema design](https://www.apollographql.com/tutorials/schema-design-best-practices) course on Odyssey.
+
+Not an enterprise customer? [Learn about GraphOS for Enterprise.](https://www.apollographql.com/pricing)
+
+
+
+Entities are the core building blocks of a federated graph, 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 subgraphs to define any entities at all with Apollo Federation, the federated schema design process often begins by thinking about what the initial entity 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](/graphos/reference/federation/subgraph-spec/) indicates that an Object or Interface type can be made into an entity by adding the `@key` directive to its definition in a subgraph schema. The `@key` directive defines a unique key for the entity and its `fields` argument will contain one or more of the type's fields. In the following example, the `Product` entity's primary key would be its `upc` field:
+
+```graphql title="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 query 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 subgraph as the return type corresponding to a `product` field on a `Review` type defined in reviews subgraph:
+
+```graphql title="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:
+
+```graphql title="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 composition errors.
+
+## Work from the entities outward
+
+When migrating from a client-only or monolithic GraphQL 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.
+
+## `@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](https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md). The GraphOS Router can [defer resolution of fields in entities](/graphos/routing/operations/defer) (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 operations.
+
+## Next steps
+
+If you haven't already, follow the [Write Federated Schemas](/graphos/schema-design/federated-schemas/entities/intro) guide to learn how to define your first entity.
+
+To learn about more advanced ways of using entities, check out these guides:
+
+- [Define Advanced Keys](/graphos/schema-design/federated-schemas/entities/define-keys), including compound and nested key fields
+- [Contribute and Reference Entity Fields](/graphos/schema-design/federated-schemas/entities/contribute-fields), including computed fields
diff --git a/docs/source/entities/contribute-fields.mdx b/docs/source/schema-design/federated-schemas/entities/contribute-fields.mdx
similarity index 100%
rename from docs/source/entities/contribute-fields.mdx
rename to docs/source/schema-design/federated-schemas/entities/contribute-fields.mdx
diff --git a/docs/source/entities/define-advanced-keys.mdx b/docs/source/schema-design/federated-schemas/entities/define-advanced-keys.mdx
similarity index 100%
rename from docs/source/entities/define-advanced-keys.mdx
rename to docs/source/schema-design/federated-schemas/entities/define-advanced-keys.mdx
diff --git a/docs/source/schema-design/federated-schemas/entities/enforce-ownership.mdx b/docs/source/schema-design/federated-schemas/entities/enforce-ownership.mdx
new file mode 100644
index 000000000..bcbb897df
--- /dev/null
+++ b/docs/source/schema-design/federated-schemas/entities/enforce-ownership.mdx
@@ -0,0 +1,279 @@
+---
+title: Enforcing Entity Ownership in Apollo Federation
+subtitle: Designating entity ownership in Apollo Federation 2
+description: Learn how to designate entity ownership and make "entity extension" a first-class concept in your Apollo Federation 2 supergraph.
+published: 2023-02-16
+id: TN0036
+tags: [federation]
+redirectFrom:
+ - /technotes/TN0036-owner-pattern/
+---
+
+In Federation 2, the notion of "extending" an entity type is strictly conceptual. All definitions of a type in different subgraphs are merged according to the "shareability" of fields. In the following example, neither subgraph really owns or extends the `Product` entity. Instead, they both contribute fields to it.
+
+
+
+```graphql title="subgraph-a.graphql"
+type Product @key(fields: "id") {
+ id: ID!
+ name: String
+}
+```
+
+```graphql title="subgraph-b.graphql"
+type Product @key(fields: "id") {
+ id: ID!
+ reviews: [Review]
+}
+```
+
+
+
+Federation 1 required that one of these definitions used the `extend` keyword or `@extends` directive. Federation 2 drops this requirement to improve the flexibility of composition and reduce the possibility of hard composition errors.
+
+However, in some situations you still might want to designate an "owner" of an entity and make "entity extension" a first-class concept in your supergraph.
+
+One example is the ability assert which subgraph is responsible for documenting an entity. If two subgraphs add different descriptions to a type, composition selects one of those descriptions and emits a hint informing you of the inconsistency:
+
+```
+HINT: [INCONSISTENT_DESCRIPTION]: Element "Product" has inconsistent
+descriptions across subgraphs. The supergraph will use description
+(from subgraph "one"):
+ """
+ The Product type.
+ """
+In subgraph "two", the description is:
+ """
+ This is my description of the Product type.
+ """
+```
+
+
+
+When a description is inconsistent across subgraphs, composition selects the description from the first subgraph alphabetically by name.
+
+
+
+A mechanism for deciding the "owner" of the type allows tools such as linters to catch these inconsistencies early in the development process.
+
+## Creating an `@owner` directive
+
+You can add an `@owner` directive to your supergraph using the [`@composeDirective`](/graphos/reference/federation/directives#composedirective) functionality introduced in Federation 2.2.
+
+```graphql title="subgraph-a.graphql"
+extend schema
+ @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@key", "@composeDirective"])
+ @link(url: "https://graphql.mycompany.dev/owner/v1.0", import: ["@owner"])
+ @composeDirective(name: "@owner")
+
+directive @owner(team: String!) on OBJECT
+
+type Product @key(fields: "id") @owner(team: "subgraph-a") {
+ id: ID!
+ name: String
+}
+```
+
+The `@owner` directive now appears in the supergraph. Because we did not define the directive as `repeatable`, subgraphs cannot define it with different arguments.
+
+
+
+```graphql title="supergraph.graphql" {69}
+schema
+ @link(url: "https://specs.apollo.dev/link/v1.0")
+ @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION)
+ @link(url: "https://graphql.mycompany.dev/owner/v1.0", import: ["@owner"]) {
+ query: Query
+}
+
+directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE
+
+directive @join__field(
+ graph: join__Graph
+ requires: join__FieldSet
+ provides: join__FieldSet
+ type: String
+ external: Boolean
+ override: String
+ usedOverridden: Boolean
+) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
+
+directive @join__graph(name: String!, url: String!) on ENUM_VALUE
+
+directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE
+
+directive @join__type(
+ graph: join__Graph!
+ key: join__FieldSet
+ extension: Boolean! = false
+ resolvable: Boolean! = true
+ isInterfaceObject: Boolean! = false
+) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
+
+directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION
+
+directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA
+
+directive @owner(team: String!) on OBJECT
+
+scalar join__FieldSet
+
+enum join__Graph {
+ ONE @join__graph(name: "one", url: "http://localhost:4001")
+}
+
+scalar link__Import
+
+enum link__Purpose {
+ """
+ `SECURITY` features provide metadata necessary to securely resolve fields.
+ """
+ SECURITY
+
+ """
+ `EXECUTION` features provide metadata necessary for operation execution.
+ """
+ EXECUTION
+}
+
+type Product @join__type(graph: ONE, key: "id") @owner(team: "subgraph-a") {
+ id: ID!
+ name: String
+}
+
+type Query @join__type(graph: ONE) {
+ products: [Product]
+}
+```
+
+
+
+## Writing a lint rule using the `@owner` directive
+
+Here's an example of a [`@graphql-eslint`](https://the-guild.dev/graphql/eslint/docs) rule for subgraph schemas that uses the `@owner` directive to determine if a description is required:
+
+
+
+```js
+const { getDirective } = require("@graphql-tools/utils");
+const { buildSchema } = require("graphql");
+
+module.exports = {
+ rules: {
+ /** @type {import("@graphql-eslint/eslint-plugin").GraphQLESLintRule} */
+ "subgraph-owned-type-has-description": {
+ create(context) {
+ const schema = buildSchema(context.getSourceCode().text, {
+ assumeValidSDL: true, // subgraph schemas may not be valid on their own
+ });
+
+ return {
+ /**
+ * For each object type defintion, look for an `@owner` directive.
+ * If it exist, require a description.
+ * If it doesn't, disallow a description.
+ */
+ ObjectTypeDefinition(node) {
+ const type = schema.getType(node.name.value);
+ const owner = getDirective(schema, type, "owner");
+
+ if (owner && !node.description) {
+ context.report({
+ node,
+ message: "Description is required on owned types",
+ });
+ }
+
+ if (!owner && node.description) {
+ context.report({
+ node,
+ message: "Description not allowed on unowned types",
+ });
+ }
+ },
+ };
+ },
+ },
+ },
+};
+```
+
+
+
+## Using `@owner` to determine required approvers
+
+Another use case for the `@owner` directive is to determine required reviewers when a schema change affects a type owned by another team.
+
+The exact process depends on your source control and continuous integration systems. The following example steps assume you're using GitHub for both.
+
+1. Add a `pull_request` workflow:
+
+ ```yaml title=".github/workflows/add-reviewers.yaml"
+ name: Add required reviewers for owned GraphQL types
+ on: [pull_request]
+ ```
+
+2. Determine the affected types in the schema change:
+
+ ```js
+ import { diff } from "@graphql-inspector/core";
+ import { buildSchema } from "graphql";
+
+ const differences = diff(
+ buildSchema(schemaFromBaseRef, { assumeValidSDL: false }),
+ buildSchema(schemaFromCurrentRef, { assumeValidSDL: false })
+ );
+
+ /* Derive a list of affected types from the result:
+ [
+ {
+ "criticality": {
+ "level": "NON_BREAKING"
+ },
+ "type": "FIELD_ADDED",
+ "message": "Field 'newField' was added to object type 'Product'",
+ "path": "Product.newField"
+ }
+ ]
+ */
+ ```
+
+3. Obtain the supergraph schema.
+
+ You can use [`rover supergraph fetch`](https://www.apollographql.com/docs/rover/commands/supergraphs#supergraph-fetch) or retrieve it using the [Apollo Platform API](https://studio.apollographql.com/public/apollo-platform/explorer?explorerURLState=N4IgJg9gxgrgtgUwHYBcQC4QEcYIE4CeABAOIIoDKMADvgOZ4CG1AFgBQAkeCAZukQEkAIgEIAlEWAAdJESIA3RngCWjVG258iXXhOmy5RAPpGUBWkkaIZhogDoHRCLJJNWANSWrUkm7aIANowoCADOKACC1NR4EPIIYAAyjDBIUCy%2BBv5EAEYwygFgmdm23KEwASjFJbYmZhZWCH41cg52TrIAQvmFVFBQYaHVLYZQENwU6QhwjMMjo%2BMIQtDwyCjN8wC%2BGzXbWSV7uztEh4ane5sgm0A&variant=main).
+
+4. Extract the owners for the affected types:
+
+ ```js
+ import { getDirective } from "@graphql-tools/utils";
+
+ const supergraphSchema = buildSchema(supergraphSdl);
+ const affectedTeams = [];
+
+ for (const typeName of affectedTypes) {
+ const type = supergraphSchema.getType(typeName);
+
+ const owner = getDirective(schema, type, "owner")?.[0];
+
+ if (owner) {
+ affectedTeams.push(owner.team);
+ }
+ }
+ ```
+
+5. Add the team as reviewers on the pull request:
+
+ ```js
+ import { Octokit } from "@octokit/action";
+
+ const octokit = new Octokit();
+
+ const [owner, repo] = process.env.GITHUB_REPOSITORY.split("/");
+
+ await octokit.pulls.requestReviewers({
+ owner,
+ repo,
+ pull_number: pullNumber, // ${{ github.event.number }}
+ team_reviewers: affectedTeams,
+ });
+ ```
diff --git a/docs/source/entities/interfaces.mdx b/docs/source/schema-design/federated-schemas/entities/interfaces.mdx
similarity index 100%
rename from docs/source/entities/interfaces.mdx
rename to docs/source/schema-design/federated-schemas/entities/interfaces.mdx
diff --git a/docs/source/schema-design/federated-schemas/entities/intro.mdx b/docs/source/schema-design/federated-schemas/entities/intro.mdx
new file mode 100644
index 000000000..ec12d03b5
--- /dev/null
+++ b/docs/source/schema-design/federated-schemas/entities/intro.mdx
@@ -0,0 +1,170 @@
+---
+title: Introduction to Entities
+subtitle: Resolve federated types across multiple subgraphs
+description: Learn to define, contribute to, and reference object types that resolve their fields across multiple subgraphs in a federated GraphQL architecture.
+redirectFrom:
+ - /federation/entities
+---
+
+Federated schemas let multiple subgraphs collaboratively define and resolve fields for shared object types.
+This guide shows you how to define a shared object type called an _entity_.
+
+Before you get started, you may want to check out the [Introduction to Apollo Federation](/graphos/schema-design/federated-schemas/federation) for a conceptual overview.
+
+## Entity overview
+
+_Entities_ are a fundamental aspect of federated schemas.
+In a supergraph, an entity is an object type that can resolve its fields across multiple subgraphs.
+Each subgraph can contribute different fields to the entity and is responsible for resolving only the fields that it contributes.
+This enables subgraphs to adhere to the separation of concerns principle.
+
+For example, this `Product` entity's fields are defined and resolved across two subgraphs:
+
+
+
+```graphql title="Products subgraph"
+type Product @key(fields: "upc") {
+ upc: ID!
+ name: String!
+ price: Int
+}
+```
+
+```graphql title="Reviews subgraph"
+type Product @key(fields: "productUpc") {
+ productUpc: ID!
+ rating: Int!
+}
+```
+
+
+
+
+
+Only object types can be entities.
+
+
+
+This guide goes over how to define entities in your subgraph schemas and code.
+
+## Defining an entity
+
+To define an entity within a particular subgraph, you do the following:
+
+1. Apply the [`@key` directive](#1-define-a-key) to an object type.
+2. Define the object type's [reference resolver](#2-define-a-reference-resolver).
+
+
+
+
+
+
+
+### 1. Define a `@key`
+
+In a subgraph schema, you can designate any object type as an entity by adding the `@key` directive to its definition, like so:
+
+```graphql {1} title="Products subgraph"
+type Product @key(fields: "upc") {
+ upc: ID!
+ name: String!
+ price: Int
+}
+```
+
+The `@key` directive defines an entity's _unique key_, which consists of one or more of the type's `fields`.
+In the previous example, the `Product` entity's unique key is its `upc` field.
+Every instance of an entity must be uniquely identifiable by its `@key` field(s).
+Key fields' uniqueness enable your router to associate fields from different subgraphs with the same entity instance.
+
+In most cases, the `@key` field(s) for the same entity will be the same across subgraphs.
+For example, if one subgraph uses `upc` as the `@key` field for the `Product` entity, other subgraphs should likely do the same.
+However, this [isn't strictly required](/graphos/schema-design/federated-schemas/entities/define-keys/#differing-keys-across-subgraphs).
+
+If coming from a database context, it can be helpful to think of a `@key` as an entity's [primary key](https://en.wikipedia.org/wiki/Primary_key).
+This term isn't completely accurate for entities since a single entity can have [multiple `@key`s](/graphos/schema-design/federated-schemas/entities/define-keys/#multiple-keys). The field(s) you select for an entity's `@key` must, however, uniquely identify the entity.
+In that way, `@key`s are similar to [candidate keys](https://en.wikipedia.org/wiki/Candidate_key).
+
+
+
+```graphql title="Products subgraph"
+type Product @key(fields: "upc") {
+ upc: ID!
+ name: String!
+ price: Int
+}
+```
+
+```graphql title="Reviews subgraph"
+type Product @key(fields: "productUpc") {
+ productUpc: ID!
+ inStock: Boolean!
+}
+```
+
+
+
+For more information on advanced key options, like defining [multiple keys](/graphos/schema-design/federated-schemas/entities/define-keys/#multiple-keys) or [compound keys](/graphos/schema-design/federated-schemas/entities/define-keys/#compound-keys), see the guide on [Defining keys](/graphos/schema-design/federated-schemas/entities/define-keys).
+
+#### Key field limitations
+
+An entity's `@key` cannot include:
+
+- Fields that return a union or interface
+- Fields that take arguments
+
+Though not strictly required, it's best to use non-nullable fields for keys. If you use fields that return `null` values, GraphOS may encounter issues resolving the entity.
+
+### 2. Define a reference resolver
+
+The `@key` directive effectively tells the router, "This subgraph can resolve an instance of this entity if you provide its unique key." For this to be true, the subgraph must define a _reference resolver_ for the entity.
+
+
+
+This section describes how to create reference resolvers in Apollo Server.
+If you're using another [subgraph-compatible library](/graphos/reference/federation/compatible-subgraphs), see its documentation for creating reference resolvers or the equivalent functionality.
+
+
+
+For the `Product` entity defined [above](#1-define-a-key), the reference resolver might look like this:
+
+```js {4-6} title="resolvers.js"
+// Products subgraph
+const resolvers = {
+ Product: {
+ __resolveReference(productRepresentation) {
+ return fetchProductByID(productRepresentation.upc);
+ }
+ },
+ // ...other resolvers...
+}
+```
+
+Let's break this example down:
+
+- You declare an entity's reference resolver in your resolver map, as a member of the entity's corresponding object.
+- A reference resolver's name is always `__resolveReference`.
+- A reference resolver's first parameter is a representation of the entity being resolved.
+ - An entity representation is an object that contains the entity's `@key` fields, plus its `__typename` field. These values are automatically provided to your subgraph by your router.
+- A reference resolver is responsible for returning all of the entity fields that this subgraph defines.
+ - In this example, the hypothetical `fetchProductByID` function fetches a particular `Product`'s field data based on its `upc`.
+
+
+
+A particular reference resolver might be called many times to resolve a single query. It's crucial that reference resolvers account for "N+1" issues (typically via [data loaders](https://github.com/graphql/dataloader)). For details, see [Handling the N+1 problem](/graphos/schema-design/guides/handling-n-plus-one).
+
+
+
+Every subgraph that contributes at least one unique field to an entity must define a reference resolver for that entity.
+
+To learn more about `__resolveReference` in Apollo Server, see the [API docs](/apollo-server/using-federation/api/apollo-subgraph/#__resolvereference).
+
+## Next steps
+
+Once you [add your subgraphs](/graphos/platform/graph-management/add-subgraphs) to your supergraph, GraphOS composes them into a supergraph schema.
+Clients querying your supergraph can interact with entity fields without needing to know the details of which subgraphs contribute which fields.
+
+To learn about more advanced ways of using entities, check out these guides:
+
+- [Define Advanced Keys](/graphos/schema-design/federated-schemas/entities/define-keys), including compound and nested key fields
+- [Contribute and Reference Entity Fields](/graphos/schema-design/federated-schemas/entities/contribute-fields), including computed fields
diff --git a/docs/source/entities/migrate-fields.mdx b/docs/source/schema-design/federated-schemas/entities/migrate-fields.mdx
similarity index 99%
rename from docs/source/entities/migrate-fields.mdx
rename to docs/source/schema-design/federated-schemas/entities/migrate-fields.mdx
index 849be1547..8a0afa770 100644
--- a/docs/source/entities/migrate-fields.mdx
+++ b/docs/source/schema-design/federated-schemas/entities/migrate-fields.mdx
@@ -4,7 +4,7 @@ subtitle: Transfer entity fields from one subgraph to another
description: Learn how to safely move parts of one subgraph to another subgraph in a federated GraphQL architecture using the @override directive.
---
-import ProgressiveOverrideEnterprise from '../../shared/progressive-override-enterprise.mdx';
+import ProgressiveOverrideEnterprise from '../../../../shared/progressive-override-enterprise.mdx';
As your supergraph grows, you might want to move parts of one subgraph to another subgraph.
For example, suppose your Payments subgraph defines a `Bill` entity:
diff --git a/docs/source/entities/resolve-another-subgraphs-fields.mdx b/docs/source/schema-design/federated-schemas/entities/resolve-another-subgraphs-fields.mdx
similarity index 100%
rename from docs/source/entities/resolve-another-subgraphs-fields.mdx
rename to docs/source/schema-design/federated-schemas/entities/resolve-another-subgraphs-fields.mdx
diff --git a/docs/source/entities/use-contexts.mdx b/docs/source/schema-design/federated-schemas/entities/use-contexts.mdx
similarity index 100%
rename from docs/source/entities/use-contexts.mdx
rename to docs/source/schema-design/federated-schemas/entities/use-contexts.mdx
diff --git a/docs/source/schema-design/federated-schemas/federation.mdx b/docs/source/schema-design/federated-schemas/federation.mdx
new file mode 100644
index 000000000..37896827f
--- /dev/null
+++ b/docs/source/schema-design/federated-schemas/federation.mdx
@@ -0,0 +1,91 @@
+---
+title: Introduction to Apollo Federation
+subtitle: Learn how federation combines your GraphQL APIs into a unified supergraph
+description: Learn how Apollo Federation can help you declaratively combine your services into a unified, federated GraphQL API using a microservices architecture.
+redirectFrom:
+ - /federation
+---
+
+Apollo Federation lets you declaratively combine multiple APIs into a single, federated graph. This federated graph enables clients to interact with your APIs through a single request.
+
+A client makes a request to the federated GraphQL API's single entry point called the _router_. The router intelligently orchestrates and distributes the request across your APIs and returns a unified response. For a client, the request and response cycle of querying the router looks the same as querying any GraphQL server.
+
+
+
+
+
+
+Your federated GraphQL API, or _graph_, can be made of GraphQL APIs and other data sources.
+[Learn how Apollo Connectors](../connectors/) simplify incorporating REST APIs into your graph.
+
+
+
+
+To jump into building a federated GraphQL API, check out the [Apollo GraphOS Quickstart](/graphos/get-started/guides/quickstart).
+
+
+
+
+
+
+
+## Benefits of federation
+
+### Microservices architecture
+
+Apollo Federation lets API teams operate in a [microservices architecture](https://www.atlassian.com/microservices/microservices-architecture/microservices-vs-monolith) while exposing a unified GraphQL API to clients. Understanding these concepts can help you get the most out of federation.
+
+- Learn more about the [considerations and benefits of GraphQL](https://graphql.com/learn/what-is-graphql/).
+- Learn more about the [considerations and benefits of microservices architecture](https://aws.amazon.com/compare/the-difference-between-monolithic-and-microservices-architecture/).
+
+### Preserve client simplicity and performance
+
+A client may need to make multiple requests when interacting with multiple non-federated GraphQL APIs. This can happen when an organization adopting GraphQL has multiple teams developing APIs independently. Each team sets up a GraphQL API that provides the data used by that team. For example, a travel app may have separate GraphQL APIs for users, flights, and hotels:
+
+
+
+
+
+With a single federated graph, you preserve a powerful advantage of GraphQL over traditional REST APIs: the ability to fetch all the data you need in a single request.
+
+
+
+
+
+The router intelligently calls all the APIs it needs to complete requests rather than simply forwarding them.
+For performance and security reasons, clients should only query the router, and only the router should query the constituent APIs.
+No client-side configuration is required.
+
+### Design schemas at scale
+
+Some alternative approaches to combining GraphQL APIs impose limits on your schema, like adding namespaces or representing relationships with IDs instead of types. With these approaches, your individual GraphQL API schemas may look unchangedβbut the resulting federated schema that clients interact with is more complex. Subsequently, it requires you to make frontend as well as backend changes.
+
+With Apollo Federation, clients can interact with the federated schema as if it were a monolith. Consumers of your API shouldn't know or care that it's implemented as microservices.
+
+### Maintain a single API
+
+With federation, every team contributes directly to the overall federated GraphQL schema. Each team can work independently without needing to maintain multiple API layers. This frees your platform team to focus on the quality of your API rather than keeping it up to date.
+
+## Next steps
+
+Before continuing, it's helpful to know some terminology:
+
+- When combining multiple GraphQL APIs, the single, federated graph is called a _supergraph_.
+- In a supergraph, the constituent APIs are called _subgraphs_.
+
+
+
+
+Different subgraphs in the same supergraph can use different server implementations and even different programming languages as long as they are [federation-compatible](../../reference/federation/compatible-subgraphs).
+
+Ready to get started?
+
+- Create and run a federated graph with the [Quickstart](/graphos/get-started/guides/quickstart).
+
+- Connect REST APIs to your graph using Apollo Connectors with the [REST quickstart](/graphos/get-started/guides/rest-quickstart).
+
+### Additional resources
+
+Depending on your goals, you have several options for learning more about federation:
+- If you're new to federated architecture, this [overview article](https://graphql.com/learn/federated-architecture/) can familiarize the concepts.
+- If you learn best by doing, this [interactive course](https://www.apollographql.com/tutorials/voyage-part1) teaches you to build an example supergraph using Apollo Federation.
diff --git a/docs/source/schema-design/federated-schemas/schema-types.mdx b/docs/source/schema-design/federated-schemas/schema-types.mdx
new file mode 100644
index 000000000..6ccb51db1
--- /dev/null
+++ b/docs/source/schema-design/federated-schemas/schema-types.mdx
@@ -0,0 +1,235 @@
+---
+title: Federated Schemas
+subtitle: Learn about the different types of GraphQL schemas
+description: Learn about subgraph, supergraph, and API schemas in federated GraphQL architectures.
+redirectFrom:
+ - /federation/federated-schemas/
+ - /federation/federated-types/
+---
+
+A federated supergraph uses multiple "types" of GraphQL schemas:
+
+```mermaid
+graph TB;
+ serviceA[Subgraph schema A];
+ serviceB[Subgraph schema B];
+ serviceC[Subgraph schema C];
+ composition[["π Composition "]];
+ supergraph{{"Supergraph schema (A + B + C + routing machinery)"}};
+ api(["API schema (A + B + C)"]);
+ serviceA & serviceB & serviceC --> composition;
+ composition -- "(Composition succeeds)" --> supergraph;
+ supergraph -- "(Remove routing machinery)" --> api;
+ class composition tertiary;
+```
+
+* **Subgraph schemas.** Each subgraph has a distinct schema that indicates which types and fields of your composed supergraph it can resolve.
+ * These are the only schemas that your teams define manually.
+* **Supergraph schema.** This schema combines all of the types and fields from your subgraph schemas, plus some federation-specific information that tells your router which subgraphs can resolve which fields.
+ * This schema is the result of performing [composition](/graphos/schema-design/federated-schemas/composition/) on your collection of subgraph schemas.
+* **API schema.** This schema is similar to the supergraph schema, but it omits federation-specific types, fields, and directives that are considered "machinery" and are not part of your public API.
+ * This is the schema that your router exposes to clients, which don't need to know internal implementation details about your graph.
+
+Let's look at an example!
+
+## Subgraph schemas
+
+Below are example schemas for three subgraphs in an e-commerce company's supergraph. Each subgraph is implemented as a separate GraphQL API:
+
+
+
+```graphql title="Users"
+type Query {
+ me: User
+}
+
+type User @key(fields: "id") {
+ id: ID!
+ username: String! @shareable
+}
+
+# (Subgraph schemas include
+# this to opt in to
+# Federation 2 features.)
+extend schema
+ @link(url: "https://specs.apollo.dev/federation/v2.3",
+ import: ["@key", "@shareable"])
+```
+
+```graphql title="Products"
+type Query {
+ topProducts(first: Int = 5): [Product]
+}
+
+type Product @key(fields: "upc") {
+ upc: String!
+ name: String!
+ price: Int
+}
+
+extend schema
+ @link(url: "https://specs.apollo.dev/federation/v2.3",
+ import: ["@key", "@shareable"])
+```
+
+
+
+
+
+```graphql title="Reviews"
+type Review {
+ body: String
+ author: User @provides(fields: "username")
+ product: Product
+}
+
+type User @key(fields: "id") {
+ id: ID!
+ username: String! @external
+ reviews: [Review]
+}
+
+type Product @key(fields: "upc") {
+ upc: String!
+ reviews: [Review]
+}
+
+# (This subgraph uses additional
+# federated directives)
+extend schema
+ @link(url: "https://specs.apollo.dev/federation/v2.3",
+ import: ["@key", "@shareable", "@provides", "@external"])
+```
+
+
+
+As these schemas show, multiple subgraphs can contribute unique fields to a single type. For example, the Products subgraph and the Reviews subgraph both contribute fields to the `Product` type.
+
+## Supergraph schema
+
+The supergraph schema is the output of [schema composition](/graphos/schema-design/federated-schemas/composition/). It serves the following purposes:
+
+* It provides your router with the name and endpoint URL for each of your subgraphs.
+* It includes all types and fields defined by all of your subgraphs.
+* It tells your router which of your subgraphs can resolve which GraphQL fields.
+
+Here's the supergraph schema composed with [the subgraph schemas above](#subgraph-schemas):
+
+
+
+```graphql
+schema
+ @link(url: "https://specs.apollo.dev/link/v1.0")
+ @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION)
+{
+ query: Query
+}
+
+directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE
+
+directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
+
+directive @join__graph(name: String!, url: String!) on ENUM_VALUE
+
+directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE
+
+directive @join__type(graph: join__Graph!, key: join__FieldSet, extension: Boolean! = false, resolvable: Boolean! = true, isInterfaceObject: Boolean! = false) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
+
+directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION
+
+directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA
+
+scalar join__FieldSet
+
+enum join__Graph {
+ PRODUCTS @join__graph(name: "products", url: "http://localhost:4002/graphql")
+ REVIEWS @join__graph(name: "reviews", url: "http://localhost:4003/graphql")
+ USERS @join__graph(name: "users", url: "http://localhost:4001/graphql")
+}
+
+scalar link__Import
+
+enum link__Purpose {
+ """
+ `SECURITY` features provide metadata necessary to securely resolve fields.
+ """
+ SECURITY
+
+ """
+ `EXECUTION` features provide metadata necessary for operation execution.
+ """
+ EXECUTION
+}
+
+type Product
+ @join__type(graph: PRODUCTS, key: "upc")
+ @join__type(graph: REVIEWS, key: "upc")
+{
+ upc: String!
+ name: String! @join__field(graph: PRODUCTS)
+ price: Int @join__field(graph: PRODUCTS)
+ reviews: [Review] @join__field(graph: REVIEWS)
+}
+
+type Query
+ @join__type(graph: PRODUCTS)
+ @join__type(graph: REVIEWS)
+ @join__type(graph: USERS)
+{
+ topProducts(first: Int = 5): [Product] @join__field(graph: PRODUCTS)
+ me: User @join__field(graph: USERS)
+}
+
+type Review
+ @join__type(graph: REVIEWS)
+{
+ body: String
+ author: User @join__field(graph: REVIEWS, provides: "username")
+ product: Product
+}
+
+type User
+ @join__type(graph: REVIEWS, key: "id")
+ @join__type(graph: USERS, key: "id")
+{
+ id: ID!
+ username: String! @join__field(graph: REVIEWS, external: true) @join__field(graph: USERS)
+ reviews: [Review] @join__field(graph: REVIEWS)
+}
+```
+
+
+
+As you can see, the supergraph schema includes a lot of Federation-specific additions! These additions are used only by the router, and you'll never need to add them manually.
+
+## API schema
+
+The router uses its [supergraph schema](#supergraph-schema) to produce an **API schema**, which it exposes to clients as your actual GraphQL API. This schema cleanly and logically represents the combination of your [subgraph schemas](#subgraph-schemas):
+
+```graphql
+type Product {
+ name: String!
+ price: Int
+ reviews: [Review]
+ upc: String!
+}
+
+type Query {
+ me: User
+ topProducts(first: Int = 5): [Product]
+}
+
+type Review {
+ author: User
+ body: String
+ product: Product
+}
+
+type User {
+ id: ID!
+ reviews: [Review]
+ username: String!
+}
+```
+
+Unlike the supergraph schema, this schema hides the fact that your GraphQL API is composed of multiple distinct GraphQL APIs.
diff --git a/docs/source/schema-design/federated-schemas/sharing-types.mdx b/docs/source/schema-design/federated-schemas/sharing-types.mdx
new file mode 100644
index 000000000..3a886fe35
--- /dev/null
+++ b/docs/source/schema-design/federated-schemas/sharing-types.mdx
@@ -0,0 +1,637 @@
+---
+title: Value Types in Apollo Federation
+subtitle: Share types and fields across multiple subgraphs
+description: Learn how to share GraphQL types and fields across subgraphs with Apollo Federation.
+redirectFrom:
+ - /federation/federated-types/sharing-types
+ - /federation/federated-schemas/sharing-types
+---
+
+In a federated graph, it's common to want to reuse a GraphQL type across multiple subgraphs.
+
+For example, suppose you want to define and reuse a generic `Position` type in different subgraphs:
+
+```graphql
+type Position {
+ x: Int!
+ y: Int!
+}
+```
+
+Types like this are called _value types_. This article describes how to share value types and their fields in federated graph, enabling multiple subgraphs to define and resolve them.
+
+## Sharing object types
+
+By default, in Federation 2 subgraphs, a single object field can't be defined or resolved by more than one subgraph schema.
+
+Consider the following `Position` example:
+
+β
+
+
+
+```graphql {2-3} title="Subgraph A"
+type Position {
+ x: Int!
+ y: Int!
+}
+```
+
+```graphql {2-3} title="Subgraph B"
+type Position {
+ x: Int!
+ y: Int!
+}
+```
+
+
+
+Attempting to compose these two subgraph schemas together will [break composition](/graphos/schema-design/federated-schemas/composition/#breaking-composition). The router doesn't know which subgraph is responsible for resolving `Position.x` and `Position.y`. To enable multiple subgraphs to resolve these fields, you must first mark that field as [`@shareable`](#using-shareable).
+
+
+
+As an alternative, if you want Subgraphs A and B to resolve different fields of `Position`, you can designate the `Position` type as an [entity](/graphos/schema-design/federated-schemas/entities/intro).
+
+
+
+### Using `@shareable`
+
+The `@shareable` directive enables multiple subgraphs to resolve a particular object field (or set of object fields).
+
+To use `@shareable` in a subgraph schema, you first need to add the following snippet to that schema to [opt in to Federation 2](/graphos/reference/migration/to-federation-version-2/#opt-in-to-federation-2):
+
+```graphql
+extend schema
+ @link(url: "https://specs.apollo.dev/federation/v2.3",
+ import: ["@key", "@shareable"])
+```
+
+Then you can apply the `@shareable` directive to an object type, or to individual fields of that type:
+
+β
+
+
+
+```graphql {1} title="Subgraph A"
+type Position @shareable {
+ x: Int!
+ y: Int!
+}
+```
+
+```graphql {2-3} title="Subgraph B"
+type Position {
+ x: Int! @shareable
+ y: Int! @shareable
+}
+```
+
+
+
+
+Marking a type as `@shareable` is equivalent to marking all of its fields as `@shareable`, so the two subgraph definitions above are equivalent.
+
+
+
+Both subgraphs A and B can now resolve the `x` and `y` fields for the `Position` type, and our subgraph schemas will successfully compose into a supergraph schema.
+
+#### β οΈ Important considerations for `@shareable`
+
+* If a type or field is marked `@shareable` in any subgraph, it must be marked either `@shareable` or [`@external`](/graphos/reference/federation/directives/#external) in every subgraph that defines it. Otherwise, composition fails.
+* If multiple subgraphs can resolve a field, make sure each subgraph's resolver for that field behaves identically. Otherwise, queries might return inconsistent results depending on which subgraph resolves the field.
+
+#### Using `@shareable` with `extend`
+
+If you apply `@shareable` to an object type declaration, it only applies to the fields within that exact declaration. It does not apply to other declarations for that same type:
+
+```graphql title="Subgraph A"
+type Position @shareable {
+ x: Int! # shareable
+ y: Int! # shareable
+}
+
+extend type Position {
+ # highlight-start
+ z: Int! # β οΈ NOT shareable!
+ # highlight-end
+}
+```
+
+Using the `extend` keyword, the schema above includes two different declarations for `Position`. Because only the first declaration is marked `@shareable`, `Position.z` is not considered shareable.
+
+To make `Position.z` shareable, you can do one of the following:
+
+- Mark the individual field `z` with `@shareable`.
+
+ ```graphql
+ extend type Position {
+ # highlight-start
+ z: Int! @shareable
+ # highlight-end
+ }
+ ```
+
+- Mark the entire `extend` declaration with `@shareable`.
+
+ - This strategy requires targeting v2.2 or later of the Apollo Federation specification in your subgraph schema. Earlier versions do not support applying `@shareable` to the same object type multiple times.
+
+ ```graphql
+ extend schema
+ @link(url: "https://specs.apollo.dev/federation/v2.3", import: ["@shareable"]) #highlight-line
+
+ extend type Position @shareable { #highlight-line
+ z: Int!
+ }
+ ```
+
+## Differing shared fields
+
+Shared fields can only differ in their [return types](#return-types) and [arguments](#arguments) in specific ways.
+If fields you want to share between subgraphs differ more than is permitted, use [entities](/graphos/schema-design/federated-schemas/entities/intro) instead of shareable value types.
+
+
+### Return types
+
+Let's say two subgraphs both define an `Event` object type with a `timestamp` field:
+
+β
+
+
+
+```graphql {2} title="Subgraph A"
+type Event @shareable {
+ timestamp: Int!
+}
+```
+
+```graphql {2} title="Subgraph B"
+type Event @shareable {
+ timestamp: String!
+}
+```
+
+
+
+Subgraph A's `timestamp` returns an `Int`, and Subgraph B's returns a `String`. This is invalid. When composition attempts to generate an `Event` type for the supergraph schema, it fails due to an unresolvable conflict between the two `timestamp` field definitions.
+
+Next, look at these varying definitions for the `Position` object type:
+
+β
+
+
+
+```graphql {2-3} title="Subgraph A"
+type Position @shareable {
+ x: Int!
+ y: Int!
+}
+```
+
+```graphql {2-3} title="Subgraph B"
+type Position @shareable {
+ x: Int
+ y: Int
+}
+```
+
+
+
+The `x` and `y` fields are non-nullable in Subgraph A, but they're nullable in Subgraph B. This is valid. Composition recognizes that it can use the following definition for `Position` in the supergraph schema:
+
+
+```graphql title="Supergraph schema"
+type Position {
+ x: Int
+ y: Int
+}
+```
+
+This definition works for querying Subgraph A, because Subgraph A's definition is more restrictive than this (a non-nullable value is always valid for a nullable field). In this case, composition coerces Subgraph A's `Position` fields to satisfy the reduced restrictiveness of Subgraph B.
+
+
+
+Subgraph A's actual subgraph schema is not modified. Within Subgraph A, `x` and `y` remain non-nullable.
+
+
+
+### Arguments
+
+Arguments for a shared field can differ between subgraphs in certain ways:
+
+* If an argument is required in at least one subgraph, it can be optional in other subgraphs. It cannot be omitted.
+* If an argument is optional in every subgraph where it's defined, it is technically valid to omit it in other subgraphs. However:
+ * β οΈ If a field argument is omitted from any subgraph, that argument is omitted from the supergraph schema entirely. This means that clients can't provide the argument for that field.
+
+β
+
+
+
+```graphql {3} title="Subgraph A"
+type Building @shareable {
+ # Argument is required
+ height(units: String!): Int!
+}
+```
+
+```graphql {3} title="Subgraph B"
+type Building @shareable {
+ # Argument can be optional
+ height(units: String): Int!
+}
+```
+
+
+
+β
+
+
+
+```graphql {3} title="Subgraph A"
+type Building @shareable {
+ # Argument is required
+ height(units: String!): Int!
+}
+```
+
+```graphql {3} title="Subgraph B"
+type Building @shareable {
+ # β οΈ Argument can't be omitted! β οΈ
+ height: Int!
+}
+```
+
+
+
+β οΈ
+
+
+
+```graphql {3} title="Subgraph A"
+type Building @shareable {
+ # Argument is optional
+ height(units: String): Int!
+}
+```
+
+```graphql {5} title="Subgraph B"
+type Building @shareable {
+ # Argument can be omitted, BUT
+ # it doesn't appear in the
+ # supergraph schema!
+ height: Int!
+}
+```
+
+
+
+For more information, see [Input types and field arguments](/graphos/schema-design/federated-schemas/composition#input-types-and-field-arguments).
+
+### Omitting fields
+
+Look at these two definitions of a `Position` object type:
+
+β οΈ
+
+
+
+```graphql title="Subgraph A"
+type Position @shareable {
+ x: Int!
+ y: Int!
+}
+```
+
+```graphql title="Subgraph B"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int!
+}
+```
+
+
+
+Subgraph B defines a `z` field, but Subgraph A doesn't. In this case, when composition generates the `Position` type for the supergraph schema, it includes all three fields:
+
+
+
+```graphql title="Supergraph schema"
+type Position {
+ x: Int!
+ y: Int!
+ z: Int!
+}
+```
+
+
+
+This definition works for Subgraph B, but it presents a problem for Subgraph A. Let's say Subgraph A defines the following `Query` type:
+
+
+
+```graphql title="Subgraph A"
+type Query {
+ currentPosition: Position!
+}
+```
+
+
+
+According to the hypothetical supergraph schema, the following query is valid against the supergraph:
+
+β
+
+
+
+```graphql
+query GetCurrentPosition {
+ currentPosition {
+ x
+ y
+ z # β οΈ Unresolvable! β οΈ
+ }
+}
+```
+
+
+
+And here's the problem: if Subgraph B doesn't define `Query.currentPosition`, this query must be executed on Subgraph A. But Subgraph A is missing the `Position.z` field, so that field is unresolvable!
+
+Composition recognizes this potential problem, and it fails with an error. To learn how to fix it, check out [Solutions for unresolvable fields](/graphos/reference/federation/composition-rules#solutions-for-unresolvable-fields).
+
+## Adding new shared fields
+
+Adding a new field to a value type can cause composition issues, because it's challenging to add the field to all defining subgraphs at the same time.
+
+Let's say we're adding a `z` field to our `Position` value type, and we start with Subgraph A:
+
+β οΈ
+
+
+
+```graphql {4} title="Subgraph A"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int!
+}
+```
+
+```graphql title="Subgraph B"
+type Position @shareable {
+ x: Int!
+ y: Int!
+}
+```
+
+
+
+It's likely that when we attempt to compose these two schemas, composition will fail, because Subgraph B can't resolve `Position.z`.
+
+To incrementally add the field to all of our subgraphs without breaking composition, we can use the [`@inaccessible` directive](#using-inaccessible).
+
+
+### Using `@inaccessible`
+
+If you apply the `@inaccessible` directive to a field, composition omits that field from your router's API schema. This helps you incrementally add a field to multiple subgraphs without breaking composition.
+
+To use `@inaccessible` in a subgraph, first make sure you include it in the `import` array of your Federation 2 opt-in declaration:
+
+```graphql {3} title="Subgraph A"
+extend schema
+ @link(url: "https://specs.apollo.dev/federation/v2.3",
+ import: ["@key", "@shareable", "@inaccessible"])
+```
+
+Then, whenever you add a new field to a value type, apply `@inaccessible` to that field if it isn't yet present in every subgraph that defines the value type:
+
+
+
+```graphql {4} title="Subgraph A"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int! @inaccessible
+}
+```
+
+```graphql title="Subgraph B"
+type Position @shareable {
+ x: Int!
+ y: Int!
+}
+```
+
+
+
+Even if `Position.z` is defined in multiple subgraphs, you only need to apply `@inaccessible` in one subgraph to omit it. In fact, you might want to apply it in only one subgraph to simplify removing it later.
+
+With the syntax above, composition omits `Position.z` from the generated API schema, and the resulting `Position` type includes only `x` and `y` fields.
+
+
+
+Notice that `Position.z` does appear in the supergraph schema, but the API schema enforces which fields clients can include in operations. [Learn more about federated schemas.](/graphos/schema-design/federated-schemas/schema-types)
+
+
+
+Whenever you're ready, you can now add `Position.z` to Subgraph B:
+
+
+
+```graphql title="Subgraph A"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int! @inaccessible
+}
+```
+
+```graphql {4} title="Subgraph B"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int!
+}
+```
+
+
+
+At this point, `Position.z` is still `@inaccessible`, so composition continues to ignore it.
+
+Finally, when you've added `Position.z` to every subgraph that defines `Position`, you can remove `@inaccessible` from Subgraph A:
+
+
+
+```graphql {4} title="Subgraph A"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int!
+}
+```
+
+```graphql title="Subgraph B"
+type Position @shareable {
+ x: Int!
+ y: Int!
+ z: Int!
+}
+```
+
+
+
+Composition now successfully includes `Position.z` in the supergraph schema!
+
+## Unions and interfaces
+
+In Federation 2, `union` and `interface` type definitions can be shared between subgraphs by default, and those definitions can differ:
+
+
+```graphql {1, 3, 9} title="Subgraph A"
+union Media = Book | Movie
+
+interface User {
+ name: String!
+}
+```
+
+```graphql {1, 3, 9} title="Subgraph B"
+union Media = Book | Podcast
+
+interface User {
+ name: String!
+ age: Int!
+}
+```
+
+
+
+[Compositional logic](/graphos/schema-design/federated-schemas/composition#merging-types-from-multiple-subgraphs) merges these definitions in your supergraph schema:
+
+```graphql title="Supergraph schema"
+union Media = Book | Movie | Podcast
+
+# The object types that implement this interface are
+# responsible for resolving these fields.
+interface User {
+ name: String!
+ age: Int!
+}
+```
+
+This can be useful when different subgraphs are responsible for different subsets of a particular set of related types or values.
+
+
+
+You can also use the `enum` type across multiple subgraphs. For details, see [Merging types from multiple subgraphs](composition#enums).
+
+
+
+### Challenges with shared interfaces
+
+Sharing an interface type across subgraphs introduces maintenance challenges whenever that interface changes. Consider these subgraphs:
+
+
+
+```graphql title="Subgraph A"
+interface Media {
+ id: ID!
+ title: String!
+}
+
+type Book implements Media {
+ id: ID!
+ title: String!
+}
+```
+
+```graphql title="Subgraph B"
+interface Media {
+ id: ID!
+ title: String!
+}
+
+type Podcast implements Media {
+ id: ID!
+ title: String!
+}
+```
+
+
+
+Now, let's say Subgraph B adds a `creator` field to the `Media` interface:
+
+β
+
+
+
+```graphql title="Subgraph A"
+interface Media {
+ id: ID!
+ title: String!
+}
+
+type Book implements Media {
+ id: ID!
+ title: String!
+ # β Doesn't define creator!
+}
+```
+
+```graphql title="Subgraph B"
+interface Media {
+ id: ID!
+ title: String!
+ creator: String! #highlight-line
+}
+
+type Podcast implements Media {
+ id: ID!
+ title: String!
+ creator: String! #highlight-line
+}
+```
+
+
+
+This breaks composition, because `Book` also implements `Media` but doesn't define the new `creator` field.
+
+To prevent this error, all implementing types across all subgraphs need to be updated to include all fields of `Media`. This becomes more and more challenging to do as your number of subgraphs and teams grows. Fortunately, there's a [solution](#solution-entity-interfaces).
+
+#### Solution: Entity interfaces
+
+Apollo Federation 2.3 introduces a powerful abstraction mechanism for interfaces, enabling you to add interface fields across subgraphs without needing to update every single implementing type.
+
+[Learn more about entity interfaces.](/graphos/schema-design/federated-schemas/entities/interfaces/)
+
+## Input types
+
+Subgraphs can share `input` type definitions, but composition merges their fields using an intersection strategy. When `input` types are composed across multiple subgraphs, only mutual fields are preserved in the supergraph schema:
+
+
+
+```graphql title="Subgraph A"
+input UserInput {
+ name: String!
+ age: Int # Not in Subgraph B
+}
+```
+
+```graphql title="Subgraph B"
+input UserInput {
+ name: String!
+ email: String # Not in Subgraph A
+}
+```
+
+
+
+Compositional logic merges only the fields that all `input` types have in common. To learn more, see [Merging input types and field arguments](/graphos/schema-design/federated-schemas/composition#input-types-and-field-arguments).
+
+```graphql title="Supergraph schema"
+input UserInput {
+ name: String!
+}
+```
+
+To learn more about how composition merges different schema types under the hood, see [Merging types during composition](/graphos/schema-design/federated-schemas/composition#merging-types-from-multiple-subgraphs).
|