import NextImage from 'next/image'
import { Callout, Cards, FileTree, Steps, Tabs } from '@theguild/components'
import cdnAccessTokenSettings from '../../../../public/docs/pages/get-started/apollo-federation/cdn-access-token-settings.png'
import createAccessToken from '../../../../public/docs/pages/get-started/apollo-federation/create-access-token.png'
import cdnAccessTokenCreate from '../../../../public/docs/pages/get-started/apollo-federation/create-cdn-access-token.png'
import createdAccessToken from '../../../../public/docs/pages/get-started/apollo-federation/created-access-token.png'
import cdnAccessTokenCreated from '../../../../public/docs/pages/get-started/apollo-federation/created-cdn-access-token.png'
import publishFirstSchemaVersionUi from '../../../../public/docs/pages/get-started/apollo-federation/publish-first-schema-version-ui.png'
import publishSecondSchemaVersionUi from '../../../../public/docs/pages/get-started/apollo-federation/publish-second-schema-version-ui.png'
import publishThirdSchemaVersionUi from '../../../../public/docs/pages/get-started/apollo-federation/publish-third-schema-version-ui.png'
import registryTokenSettings from '../../../../public/docs/pages/get-started/apollo-federation/registry-token-settings.png'
import targetOverview from '../../../../public/docs/pages/get-started/apollo-federation/target-overview.png'
import cdnTokenImage from '../../../../public/docs/pages/guides/federation-cdn-token.png'

import historyImage from '../../../../public/docs/pages/guides/history.png'
import tokenImage from '../../../../public/docs/pages/guides/token.png'

# Get started with Apollo Federation

Once you've created a Hive project of type **Federation**, you can start pushing your GraphQL
Federation subgraph schemas to the Hive registry.

> Learn more about [GraphQL federation and its benefits](/federation).

This guide will walk you through the basics of schema pushing, checking, and spin up the Hive
Gateway serving the federated GraphQL schema.

<Steps>

### Prerequisites

For this guide, we are going to use the following Subgraphs that we are going to publish to Hive.

> **Note**: If you want you can also use your own subgraphs instead of the ones we provide.

<FileTree>
  <FileTree.Folder name="subgraphs" defaultOpen>
    <FileTree.File name="users.graphql" />
    <FileTree.File name="products.graphql" />
    <FileTree.File name="reviews.graphql" />
  </FileTree.Folder>
</FileTree>

We provide the actual URLs for these running subgraphs, so we can later on send some real GraphQL
requests with our federation gateway.

- **Users**: https://federation-demo.theguild.workers.dev/users
- **Products**: https://federation-demo.theguild.workers.dev/products
- **Reviews**: https://federation-demo.theguild.workers.dev/reviews

Here's the GraphQL schema (SDL) for every subgraph we are going to publish to Hive. Save these to
files on your machine.

<Tabs items={['Users', 'Products', 'Reviews']}>

<Tabs.Tab>

```graphql filename="subgraphs/users.graphql"
extend type Query {
  me: User
  user(id: ID!): User
  users: [User]
}

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

</Tabs.Tab>

<Tabs.Tab>

```graphql filename="subgraphs/products.graphql"
extend type Query {
  topProducts(first: Int = 5): [Product]
}

type Product @key(fields: "upc") {
  upc: String!
  name: String
  price: Int
  weight: Int
}
```

</Tabs.Tab>
<Tabs.Tab>

```graphql filename="subgraphs/reviews.graphql"
type Review @key(fields: "id") {
  id: ID!
  body: String
  author: User @provides(fields: "username")
  product: Product
}

extend type User @key(fields: "id") {
  id: ID! @external
  username: String @external
  reviews: [Review]
}

extend type Product @key(fields: "upc") {
  upc: String! @external
  reviews: [Review]
}
```

</Tabs.Tab>

</Tabs>

### Hive CLI setup

As you may have noticed, Hive has created three targets under your project: `development`,
`staging`, and `production`. Each of these targets represent a different environment. You can remove
or create new targets as needed, for modelling the different environments of your project.

<NextImage
  src={targetOverview}
  alt="Project overview showing the available targets"
  className="mt-10 max-w-xl rounded-lg drop-shadow-md"
/>

For this guide we will use the `development` target.

In order to publish our subgraph schemas to the schema registry, we first need to create an registry
access token with the necessary permissions for the Hive CLI.

Select the `development` target under your Hive project and then choose the **Settings** tab. On the
Settings screen, you can manage your target's settings and access tokens.

<NextImage
  src={registryTokenSettings}
  alt="Target settings for registry token management"
  className="mt-10 max-w-xl rounded-lg drop-shadow-md"
/>

Under the **Registry Access Tokens** section, click the **Create new registry token** button. Give
your access token a name and select **Read & Write** for the permissions:

<NextImage
  alt="Create Registry Token Form"
  src={createAccessToken}
  className="mt-10 max-w-xl rounded-lg drop-shadow-md"
/>

Click on **Generate Token** button and you should get your CLI token created, with permissions to
publish GraphQL schemas.

<NextImage
  alt="Created Registry Token Form"
  src={createdAccessToken}
  className="mt-10 max-w-xl rounded-lg drop-shadow-md"
/>

Make sure to copy your token and keep it safe. **You won't be able to see it again.**

### Publish subgraphs

Now that you have your access token, and you have the base schema defined, you can publish your
schema to the registry.

We'll start with the **Users** subgraph.

If you did not yet copy the contents of the `subgraphs/users.graphql` to a local file, you can do so
now.

Run the following command in your terminal, to publish your `subgraphs/users.graphql` to the
registry. Replace `<YOUR_TOKEN_HERE>` with the access token we just created.

<Tabs items={['Binary', 'NodeJS', 'Docker']}>

{/* Binary */}

<Tabs.Tab>

```bash
hive schema:publish \
  --registry.accessToken "<YOUR_TOKEN_HERE>" \
  --service="users" \
  --url="https://federation-demo.theguild.workers.dev/users" \
  --author "John Doe" \
  --commit "First Version" \
  subgraphs/users.graphql
```

</Tabs.Tab>

{/* NodeJS */}

<Tabs.Tab>

```bash
npx hive schema:publish \
  --registry.accessToken "<YOUR_TOKEN_HERE>" \
  --service="users" \
  --url="https://federation-demo.theguild.workers.dev/users" \
  --author "John Doe" \
  --commit "First Version" \
  subgraphs/users.graphql
```

</Tabs.Tab>

{/* Docker */}

<Tabs.Tab>

For Docker, we need to mount the subgraph schema file into the container.

```bash
docker run --name graphql-hive-cli --rm \
  -v $(pwd)/subgraphs/users.graphql/:/usr/src/app/subgraphs/users.graphql \
  ghcr.io/graphql-hive/cli \
  schema:publish \
  --registry.accessToken "<YOUR_TOKEN_HERE>" \
  --service="users" \
  --url="https://federation-demo.theguild.workers.dev/users" \
  --author "John Doe" \
  --commit "First Version" \
  ./subgraphs/users.graphql
```

</Tabs.Tab>

</Tabs>

If everything goes well, you should see the following output, containing a link pointing you to the
schema version on the Hive dashboard.

```bash copy=false
✔ Published initial schema.
```

If you'll get to your target's page on Hive dashboard, you should see that it was updated with the
new schema you just published 🎉

<NextImage
  alt="First published schema version on the Hive dashboard"
  src={publishFirstSchemaVersionUi}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

<Callout type="info">
  You should also check out the **Explorer** tab: you can see the schema you just published, and
  explore the API types, fields, and arguments.
</Callout>

Next, we will publish the **Products** subgraph schema to Hive. Again, let's start by copying the
schema to a local file.

<Tabs items={['Binary', 'NodeJS', 'Docker']}>

{/* Binary */}

<Tabs.Tab>

```bash
hive schema:publish \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="products" \
  --url="https://federation-demo.theguild.workers.dev/products" \
  --author "John Doe" \
  --commit "Second Version" \
  subgraphs/products.graphql
```

</Tabs.Tab>

{/* NodeJS */}

<Tabs.Tab>

```bash
npx hive schema:publish \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="products" \
  --url="https://federation-demo.theguild.workers.dev/products" \
  --author "John Doe" \
  --commit "Second Version" \
  subgraphs/products.graphql
```

</Tabs.Tab>

{/* Docker */}

<Tabs.Tab>

For Docker, we need to mount the subgraph schema file into the container.

```bash
docker run --name graphql-hive-cli --rm \
  -v $(pwd)/subgraphs/products.graphql/:/usr/src/app/subgraphs/products.graphql \
  ghcr.io/graphql-hive/cli \
  schema:publish \
  --registry.accessToken "<YOUR_TOKEN_HERE>" \
  --service="products" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  --author "John Doe" \
  --commit "Second Version" \
  ./subgraphs/products.graphql
```

</Tabs.Tab>

</Tabs>

If everything goes well, you should see the following output:

```bash copy=false
✔ Schema published
```

After the publish process, if we had over to the Hive dashboard, we can see our new schema version
published.

<NextImage
  alt="Second published schema version on the Hive dashboard"
  src={publishSecondSchemaVersionUi}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

Last, we will publish the **Reviews** subgraph schema to Hive. Again, let's start by copying the
schema to a local file.

Then, we run the following command in your terminal.

<Tabs items={['Binary', 'NodeJS', 'Docker']}>

{/* Binary */}

<Tabs.Tab>

```bash
hive schema:publish \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  --author "John Doe" \
  --commit "My second commit" \
  subgraphs/reviews.graphql
```

</Tabs.Tab>

{/* NodeJS */}

<Tabs.Tab>

```bash
npx hive schema:publish \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  --author "John Doe" \
  --commit "My second commit" \
  subgraphs/reviews.graphql
```

</Tabs.Tab>

{/* Docker */}

<Tabs.Tab>

For Docker, we need to mount the subgraph schema file into the container.

```bash
docker run --name graphql-hive-cli --rm \
  -v $(pwd)/subgraphs/reviews.graphql/:/usr/src/app/subgraphs/reviews.graphql \
  ghcr.io/graphql-hive/cli \
  schema:publish \
  --registry.accessToken "<YOUR_TOKEN_HERE>" \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  --author "John Doe" \
  --commit "My second commit" \
  ./subgraphs/reviews.graphql
```

</Tabs.Tab>

</Tabs>

Again, if everything goes well, you should see the following output:

```bash copy=false
✔ Schema published
```

On your target's **Explorer** page now, you'll be able to see the schema of all three subgraphs 🎉

<NextImage
  alt="Third published schema version on the Hive dashboard"
  src={publishThirdSchemaVersionUi}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

Congratulations on publishing and composing your first subgraphs with the Hive schema registry!

### Hive Gateway

The next step is to spin up our GraphQL gateway that will serve the federated GraphQL schema
composed out of the subgraphs we published to the Hive schema registry.

The Gateway will delegate the requests from the clients to the appropriate subgraph services, and
then merge the results into a single response.

The Hive schema registry publishes the supergraph (artifact of the composed schemas that contains
all the information about the subgraphs and fields available) to the high-availability CDN on
Cloudflare.

The gateway can poll the supergraph from the CDN and serve the composed GraphQL schema.

```mermaid

flowchart LR
    A["Hive Gateway"] -. Poll supergraph .-> C
    subgraph hive [Hive]
      direction TB
      B[Registry] -. Publish supergraph .-> C["HA CDN
        (on Cloudflare)"]
    end
    A --> X1[GraphQL subgraph]
    A --> X2[GraphQL subgraph]
    A --> X3[GraphQL subgraph]
    X1 -.- D([Hive CLI])
    X2 -.- D
    X3 -.- D
    subgraph ci [CI/CD]
      D -- Publish schemas --> B
    end

```

#### CDN Access

For accessing the supergraph, we need to create the CDN access token from the Hive dashboard.

Navigate to your target's settings page and select the **CDN Tokens** tab.

<NextImage
  alt="CDN Token Form"
  src={cdnAccessTokenSettings}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

Click the **Create new CDN token** button, give your token a name and click **Create**.

<NextImage
  alt="CDN Token Form"
  src={cdnAccessTokenCreate}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

There will be a confirmation screen showing the CDN token you just created. Make sure to copy it and
keep it safe.

<NextImage
  alt="CDN Token Form"
  src={cdnAccessTokenCreated}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

#### Run the Gateway

Hive Gateway is the Federation Gateway that seamlessly integrates with the Hive registry. You can
run Hive Gateay either as a Docker image, binary or NPM package.

<Tabs items={['Binary', 'Docker', 'Node.js Package']}>

{/* Binary */}

<Tabs.Tab>

The single executable binary for the Hive Gateway is available without any dependencies. You can
download and setup the binary on your machine.

```sh
curl -sSL https://graphql-hive.com/install-gateway.sh | sh
```

Then you can run the Hive Gateway with the following command.

```sh
hive-gateway supergraph \
  "<hive_cdn_endpoint>" \
  --hive-cdn-key "<hive_cdn_access_key>"
```

| Parameter             | Description                      |
| --------------------- | -------------------------------- |
| `hive_cdn_endpoint`   | The endpoint of your Hive target |
| `hive_cdn_access_key` | The Hive CDN access key          |

</Tabs.Tab>

{/* Docker */}

<Tabs.Tab>

The Docker image for Hive Gateway is published to the GitHub docker registry. You can simply run the
following command to start a Hive Gateway instance from your existing Hive target.

```sh
docker run --name hive-gateway -rm \
  ghcr.io/graphql-hive/gateway supergraph \
  "<hive_cdn_endpoint>" \
  --hive-cdn-key "<hive_cdn_access_key>"
```

| Parameter               | Description                      |
| ----------------------- | -------------------------------- |
| `<hive_cdn_endpoint>`   | The endpoint of your Hive target |
| `<hive_cdn_access_key>` | The Hive CDN access key          |

</Tabs.Tab>

{/* Node.js Package */}

<Tabs.Tab>

The Gateway CLI is available as a Node.js package. You can install it using your favorite package
manager.

```sh npm2yarn
npm install @graphql-hive/gateway
```

You can then run the Gateway CLI from your existing Hive target using the following command.

```sh filename="Run Hive Gateway"
npx hive-gateway supergraph \
  "<hive_cdn_endpoint>" \
  --hive-cdn-key "<hive_cdn_access_key>"
```

| Parameter             | Description                      |
| --------------------- | -------------------------------- |
| `hive_cdn_endpoint`   | The endpoint of your Hive target |
| `hive_cdn_access_key` | The Hive CDN access key          |

</Tabs.Tab>

</Tabs>

If you now navigate to `http://localhost:4000`, you should see the Hive Gateway page with
information about the supergraph and subgraphs.

import HiveGatewayLandingPageImage from '../../../../public/docs/pages/get-started/apollo-federation/hive-gateway-landing-page.png'

<NextImage
  alt="Hive Gateway Landing Page"
  src={HiveGatewayLandingPageImage}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

Now, if you navigate to `http://localhost:4000/graphql`, you should see the GraphiQL interface where
you can write and execute queries against the supergraph.

import HiveGatewayGraphiqlImage from '../../../../public/docs/pages/get-started/apollo-federation/hive-gateway-graphiql.png'

<NextImage
  alt="Hive Gateway GraphiQL"
  src={HiveGatewayGraphiqlImage}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

Here you can execute GraphQL operations against the supergraph, which will be delegate to the single
subgraph services.

Here is a sample query to execute:

```graphql filename="Sample Query using multiple Subgraphs"
query TopProductsWithReview {
  topProducts(first: 2) {
    upc
    name
    price
    reviews {
      body
      author {
        id
        username
      }
    }
  }
}
```

[Execute Query on Hive Gateway GraphiQL](http://localhost:4000/graphql?query=query+TopProductsWithReview+%7B%0A++topProducts%28first%3A+2%29+%7B%0A++++upc%0A++++name%0A++++price%0A++++reviews+%7B%0A++++++body%0A++++++author+%7B%0A++++++++id%0A++++++++username%0A++++++%7D%0A++++%7D%0A++%7D%0A%7D)

#### Usage reporting

Up next let's report the usage from our gateway to the registry, so we can see on the dashboard how
the API is being used.

For this, we simply provide a usage reporting token in addition to our CDN access token. For this
guide, we can simply re-use the registry token we already use for the CLI.

<Tabs items={['Binary', 'Docker', 'Node.js Package']}>

{/* Binary */}

<Tabs.Tab>

```sh filename="Run Mesh Gateway with registry token"
hive-gateway supergraph \
  "<hive_cdn_endpoint>" \
  --hive-cdn-key "<hive_cdn_access_key>" \
  --hive-registry-token "<hive_registry_token>"
```

| Parameter               | Description                                 |
| ----------------------- | ------------------------------------------- |
| `<hive_cdn_endpoint>`   | The endpoint of your Hive target            |
| `<hive_cdn_access_key>` | The Hive CDN access key                     |
| `<hive_registry_token>` | The Hive registry token for usage reporting |

</Tabs.Tab>

{/* Docker */}

<Tabs.Tab>

The Docker image for Hive Gateway is published to the GitHub docker registry. You can simply run the
following command to start a Hive Gateway instance from your existing Hive target.

```sh
docker run --name hive-gateway -rm \
  ghcr.io/graphql-hive/gateway supergraph \
  "<hive_cdn_endpoint>" \
  --hive-cdn-key "<hive_cdn_access_key>" \
  --hive-registry-token "<hive_registry_token>"
```

| Parameter               | Description                                 |
| ----------------------- | ------------------------------------------- |
| `<hive_cdn_endpoint>`   | The endpoint of your Hive target            |
| `<hive_cdn_access_key>` | The Hive CDN access key                     |
| `<hive_registry_token>` | The Hive registry token for usage reporting |

</Tabs.Tab>

{/* Node.js Package */}

<Tabs.Tab>

```sh filename="Run Mesh Gateway with registry token"
npx hive-gateway supergraph \
  "<hive_cdn_endpoint>" \
  --hive-cdn-key "<hive_cdn_access_key>" \
  --hive-registry-token "<hive_registry_token>"
```

| Parameter               | Description                                 |
| ----------------------- | ------------------------------------------- |
| `<hive_cdn_endpoint>`   | The endpoint of your Hive target            |
| `<hive_cdn_access_key>` | The Hive CDN access key                     |
| `<hive_registry_token>` | The Hive registry token for usage reporting |

</Tabs.Tab>

</Tabs>

After starting the gateway with the usage reporting token, we can no execute some queries using the
gateways built-in GraphiQL interface.

```graphql filename="Sample Query using multiple Subgraphs"
query TopProductsWithReview {
  topProducts(first: 2) {
    upc
    name
    price
    reviews {
      body
      author {
        id
        username
      }
    }
  }
}
```

[Execute Query on Hive Gateway GraphiQL](http://localhost:4000/graphql?query=query+TopProductsWithReview+%7B%0A++topProducts%28first%3A+2%29+%7B%0A++++upc%0A++++name%0A++++price%0A++++reviews+%7B%0A++++++body%0A++++++author+%7B%0A++++++++id%0A++++++++username%0A++++++%7D%0A++++%7D%0A++%7D%0A%7D)

After executing the query, a few times, let's switch back to the Hive dashboard and navigate to the
insights page.

import HiveDashboardInsightsImage from '../../../../public/docs/pages/get-started/apollo-federation/hive-dashboard-insights.png'

<NextImage
  alt="Hive Gateway GraphiQL"
  src={HiveDashboardInsightsImage}
  className="mt-10 max-w-2xl rounded-lg drop-shadow-md"
/>

Here we can now see the GraphQL operations from our Gateway being reported to the registry.

### Schema checks

Hive can perform several checks on your schema before publishing it to the registry. You can use
Hive CLI to run these check and find potential breaking changes or composition issues.

To see how schema checks works, let's make a small change to our local schema file. First, we'll
start with a non-breaking change - we'll add a new field to the `Review` type under the **Reviews**
subgraph:

```graphql {6} filename="subgraphs/reviews.graphql"
type Review @key(fields: "id") {
  id: ID!
  body: String
  author: User @provides(fields: "username")
  product: Product
  verified: Boolean # new field added
}

extend type User @key(fields: "id") {
  id: ID! @external
  username: String @external
  reviews: [Review]
}

extend type Product @key(fields: "upc") {
  upc: String! @external
  reviews: [Review]
}
```

Now, run the Hive CLI with the `schema:check` command and your modified `subgraphs/reviews.graphql`
file:

<Tabs items={['Binary', 'NodeJS', 'Docker']}>

{/* Binary */}

<Tabs.Tab>

```bash
hive schema:check \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  subgraphs/reviews.graphql
```

</Tabs.Tab>

{/* NodeJS */}

<Tabs.Tab>

```bash
npx hive schema:check \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  subgraphs/reviews.graphql
```

</Tabs.Tab>

{/* Docker */}

<Tabs.Tab>

For Docker, we need to mount the subgraph schema file into the container.

```bash
docker run --name graphql-hive-cli --rm \
  -v $(pwd)/subgraphs/reviews.graphql/:/usr/src/app/subgraphs/reviews.graphql \
  ghcr.io/graphql-hive/cli \
  schema:check \
  --registry.accessToken "<YOUR_TOKEN_HERE>" \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  ./subgraphs/reviews.graphql
```

</Tabs.Tab>

</Tabs>

You should see that Hive successfully detect the change you made, and exists with a `0` exit code,
meaning that the schema is compatible, valid and has no breaking changes:

```bash copy=false
ℹ Detected 1 change

- Field verified was added to object type Review
```

Now, are going to try introduce a breaking change. To do that, we'll rename an existing field in the
GraphQL schema of the **Reviews** subgraph:

```graphql {3} filename="subgraphs/reviews.graphql"
type Review @key(fields: "id") {
  id: ID!
  bodyContents: String # renamed from body
  author: User @provides(fields: "username")
  product: Product
}

extend type User @key(fields: "id") {
  id: ID! @external
  username: String @external
  reviews: [Review]
}

extend type Product @key(fields: "upc") {
  upc: String! @external
  reviews: [Review]
}
```

<Tabs items={['Binary', 'NodeJS', 'Docker']}>

{/* Binary */}

<Tabs.Tab>

```bash
hive schema:check \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  subgraphs/reviews.graphql
```

</Tabs.Tab>

{/* NodeJS */}

<Tabs.Tab>

```bash
npx hive schema:check \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  subgraphs/reviews.graphql
```

</Tabs.Tab>

{/* Docker */}

<Tabs.Tab>

For Docker, we need to mount the subgraph schema file into the container.

```bash
docker run --name graphql-hive-cli --rm \
  -v $(pwd)/subgraphs/reviews.graphql/:/usr/src/app/subgraphs/reviews.graphql \
  ghcr.io/graphql-hive/cli \
  schema:check \
  --registry.accessToken "<YOUR_TOKEN_HERE>" \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  ./subgraphs/reviews.graphql
```

</Tabs.Tab>

</Tabs>

In that case, you'll notice that Hive CLI exists with a `1` exit code, meaning that the schema has
breaking changes, and it's not compatible with the current schema in the registry:

```bash copy=false
✖ Detected 1 error

- Breaking Change: Field rating was removed from object type Review

ℹ Detected 2 changes

- Field rating was removed from object type Review
- Field averageRating was added to object type Review
```

In addition to detecting simple breaking changes, Hive is capable of detecting composability and
compatibility issues across your subgraphs. To see how it works, let's make a small change to our
schema.

We are going to add a conflict to the **Reviews** service. We are going to add a new field (`price`)
to the `Product` type, that conflicts with the `Products` type in the **Products** service.

```graphql {17} filename="subgraphs/reviews.graphql"
type Review @key(fields: "id") {
  id: ID!
  body: String
  author: User @provides(fields: "username")
  product: Product
}

extend type User @key(fields: "id") {
  id: ID! @external
  username: String @external
  reviews: [Review]
}

extend type Product @key(fields: "upc") {
  upc: String! @external
  reviews: [Review]
  price: String # type conflicts with the products subgraph
}
```

Run the Hive CLI with the `schema:check` command again and the modified `subgraphs/reviews.graphql`
file:

<Tabs items={['Binary', 'NodeJS', 'Docker']}>

{/* Binary */}

<Tabs.Tab>

```bash
hive schema:check \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  subgraphs/reviews.graphql
```

</Tabs.Tab>

{/* NodeJS */}

<Tabs.Tab>

```bash
npx hive schema:check \
  --registry.accessToken YOUR_TOKEN_HERE \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  subgraphs/reviews.graphql
```

</Tabs.Tab>

{/* Docker */}

<Tabs.Tab>

For Docker, we need to mount the subgraph schema file into the container.

```bash
docker run --name graphql-hive-cli --rm \
  -v $(pwd)/subgraphs/reviews.graphql/:/usr/src/app/subgraphs/reviews.graphql \
  ghcr.io/graphql-hive/cli \
  schema:check \
  --registry.accessToken "<YOUR_TOKEN_HERE>" \
  --service="reviews" \
  --url="https://federation-demo.theguild.workers.dev/reviews" \
  ./subgraphs/reviews.graphql
```

</Tabs.Tab>

</Tabs>

And now you can see that the schema check process has failed, due to conflicts and inconsistencies
between the schemas:

```bash copy=false
✖ Detected 2 errors

- Breaking Change: Field Product.price changed type from Price to Int
- [reviews] Product.price - Product.price already exists in the schema. It cannot also be defined in this type extension. If this is meant to be an external field, add the $(@external) directive. > Field

ℹ Detected 1 change

- Field Product.price changed type from Price to Int
```

As you can see schema checks can help you to catch potential issues before you publish your schema
to the registry.

Usually, you would run these checks in your subgraphs CI pipeline, to ensure that your subgraph
schema integrates flawlessly with the other subgraphs in the federation project, where schema
publishes are made within the Continious Deployment (CD) pipeline to actually publish the latest
subgraph version to the schema registry.

### Next Steps

Congratulations on publishing your first subgraph schemas to the Hive schema registry, composing
your supergraph, spinning up your own Federation Gateway serving the unified GraphQL schema and
reporting the usage data!

From here you can continue to explore the Hive dashboard, or dive deeper into the documentation to
learn about all the features of the Hive platform.

<Cards>
  <Cards.Card arrow title="Learn about the Schema Registry" href="/docs/schema-registry" />
  <Cards.Card arrow title="Learn about Hive Gateway" href="/docs/gateway" />
  <Cards.Card arrow title="CI/CD Integration" href="/docs/other-integrations/ci-cd" />
</Cards>

</Steps>
