Ensure the safety of changes to your data graph
If your data graph uses Apollo Federation, see checking changes to a federated graph instead of this article.
Certain changes to your GraphQL schema (such as removing a field or type) can potentially break one of your application's clients. Apollo Studio provides schema checks to help you identify breaking changes before you make them, and to help you identify when a change won't break anything.
Schema checks are a paid feature that's available as part of Apollo Studio Team and Enterprise plans.
To enable schema checks for your data graph, first do the following:
- Set up metrics reporting to Apollo Studio from your GraphQL server.
- Set up schema registration in your continuous delivery pipeline.
- If you use schema reporting to register your schema, no additional action is required.
- Install the Apollo CLI in your development environment if you haven't yet.
After you complete the above, you can perform a test check by running the following command from your project's root directory:
# Omit 'npx' if you installed the Apollo CLI globally $ npx apollo service:check --variant production
Try changing something in your schema and see what happens! If everything is set up correctly, the command's output looks similar to the output shown in The check response.
When you check your schema with the
apollo service:check command:
- Apollo Studio generates a diff between your local schema and the schema active on the variant you are checking against (
current, by default).
- It uses this diff to determine whether the changes affect any operations that have been executed against your graph recently (you can customize this time window).
- Studio returns the diff and a list of any breaking changes found.
- The Apollo CLI prints the result of the check and returns a non-zero exit code if at least one breaking change is found.
apollo service:check outputs the diff of all detected schema changes and highlights breaking changes:
$ npx apollo service:check ✔ Loading Apollo Project ✔ Validated local schema against variant prod on service engine ✔ Compared 8 schema changes against 110 operations over the last 24 hours ✖ Found 3 breaking changes and 5 compatible changes → breaking changes found FAIL ARG_REMOVED `ServiceMutation.checkSchema` arg `gitContext` was removed FAIL FIELD_REMOVED `Schema.fieldCount` was removed FAIL FIELD_REMOVED `Schema.typeCount` was removed PASS FIELD_ADDED `SchemaTag.schemaRepoID` was added PASS FIELD_CHANGED_TYPE `ServiceMutation.uploadPartialSchema` changed type from `UploadPartialSchemaResponse!` to `CompositionResult!` PASS FIELD_DEPRECATION_REMOVED `IntrospectionSchema.fieldCount` is no longer deprecated PASS FIELD_DEPRECATION_REMOVED `IntrospectionSchema.typeCount` is no longer deprecated PASS TYPE_REMOVED `UploadPartialSchemaResponse` removed View full details at: https://studio.apollographql.com/service/example-1234/check/<DETAILS>
Each change to the schema is labeled with either
Note: Because breaking changes are detected by analyzing recent operations, your GraphQL server must be pushing analytics to Apollo Studio for schema checks to work. If there are no operation metrics to compare against, dangerous schema changes are labeled with
The CLI output also includes a Studio URL that provides full details on the changes and their impact on existing clients and operations:
Note: If you've installed schema checks on your GitHub PRs, the "Details" link in your GitHub checks will take you to the same details link in this output.
Schema checks is especially useful when you add it to your continuous integration pipeline (such as Jenkins or CircleCI). By doing so, you can obtain results and display them directly on your team's pull requests.
We recommend defining a separate CI job for each variant of your schema (production, staging, etc.) you want to validate your changes against. The
apollo service:check command returns a non-zero exit code when it detects a breaking change, meaning the job will fail when the check fails.
The following config defines a schema check job for a CircleCI pipeline. Your config's syntax varies depending on your CI tool, but the job's steps are the same.
version: 2 jobs: # ...other jobs... # Define a separate job for each environment you validate against. check_against_staging: docker: - image: circleci/node:12 steps: - checkout - run: npm install # Start the GraphQL server. If a different command is used to # start the server, use it in place of `npm start` here. - run: name: Starting server command: npm start background: true # Make sure the server has enough time to start up before running # commands against it. - run: sleep 5 # This command authenticates using the `APOLLO_KEY` environment # variable. Specify your GraphQL endpoint's URL in your Apollo config. - run: npx apollo service:check --variant=staging
If you're using GitHub, you can install the Apollo Studio GitHub app. This app enables Apollo Studio to send a webhook back to your GitHub project on each call to
apollo service:check, providing built-in pass/fail status checks on your pull requests:
If you're using GitHub Enterprise, Bitbucket, or another version control service, we recommend setting up your CI tool to post a comment on each pull request with the results of schema checks. By surfacing schema diffs and breaking changes directly in your PR, you can avoid having to search your CI logs to check why a check failed.
apollo service:check supports a
--markdown flag, which outputs the results of a schema check in markdown format. You can pipe this output directly into a comment to your source control tool, like in this example of posting a comment with the results of a schema check to GitHub.
The output of
apollo service:check --markdown looks like this:
### Apollo Service Check 🔄 Validated your local schema against `engine@staging`. 🔢 Compared **18 schema changes** against **100 operations** seen over the **last 24 hours**. ❌ Found **7 breaking changes** that would affect **3 operations** across **2 clients** 🔗 [View your service check details](https://studio.apollographql.com/service/engine/checks?...).
Not every change to a schema is a potentially breaking change. Additive changes (such as adding a field to a type) are typically safe and do not affect active clients. Deletions and modifications (such as removing a field or changing a return type), however, can break clients that use affected types and fields.
These changes remove a schema element. If a removed element is actively being used by an operation, your data graph will return an error to affected clients.
FIELD_REMOVED: Field used by at least one operation was removed
TYPE_REMOVED: Type(scalar, object) used by at least one operation was removed
ARG_REMOVED: Argument was removed from a field used by at least one operation
TYPE_REMOVED_FROM_UNION: Type was removed from a union used by at least one operation
INPUT_FIELD_REMOVED: Field removed from an input type referenced by an argument on a field used by at least one operation
VALUE_REMOVED_FROM_ENUM: A value removed from an enum used by at least one operation
TYPE_REMOVED_FROM_INTERFACE: An object removed from an interface used by at least one operation
These changes add a required input to a schema element. If an operation is actively using an element of your graph and doesn't add the new required input argument, the data graph will return an error to affected clients.
REQUIRED_ARG_ADDED: Non-nullable argument added to field used by at least one operation
NON_NULL_INPUT_FIELD_ADDED: Non-null field added to an input object used by at least one operation
These changes update an existing schema element. If an operation is actively using an element that is updated, the operation might start receiving an error from your data graph. It also might receive an unexpected result.
Note: In some cases, in-place updates are compatible with affected clients at runtime (such as a type rename or a conversion from an object to an interface that uses the same fields). However, schema checks still marks these as breaking changes, because validation does not have enough information to ensure that they are safe.
FIELD_CHANGED_TYPE: Field used by at least one operation changed return type
INPUT_FIELD_CHANGED_TYPE: Field in input object changed type and is referenced by argument on field used by at least one operation
TYPE_CHANGED_KIND: Type used by at least one operation changed, ex: scalar to object or enum to union
ARG_CHANGED_TYPE: Argument changed type on field used by at least one operation
These changes update the default value for an argument. If an operation is using an element of your graph and does not specify a value for this argument, the operation might get an unexpected result when the schema is updated if it was relying on the original default value.
ARG_DEFAULT_VALUE_CHANGE: Default value added or changed for argument on a field used by at least one operation
These changes are detected by the
apollo service:check command, but they are "safe." They will never affect the behavior of any existing clients if deployed.
- Optional arguments
OPTIONAL_ARG_ADDEDNullable argument added to a field
NULLABLE_FIELD_ADDED_TO_INPUT_OBJECTNullable field added to an input object
FIELD_ADDEDField added to a type
TYPE_ADDEDType added to the schema
VALUE_ADDED_TO_ENUMValue added to an enum. If clients contain a switch case on the enum and do not include the `default`, this change could cause unexpected behavior
TYPE_ADDED_TO_UNIONType added to a union used by at least one operation
TYPE_ADDED_TO_INTERFACEInterface added to an object used by at least one operation
FIELD_DEPRECATION_REMOVEDField no longer deprecated
FIELD_DEPRECATED_REASON_CHANGEReason for deprecation changed
ENUM_DEPRECATION_REMOVEDEnum no longer deprecated
ENUM_DEPRECATED_REASON_CHANGEReason for enum deprecation changed