Launch Apollo Studio

Contracts

Deliver subsets of your enterprise graph


Contracts are currently available as a public preview feature for Enterprise plans.

Contracts currently only support federated graphs.

Apollo Studio contracts enable you to deliver different subsets of your graph to different consumers. Each contract filters specific portions of your graph's API schema:

Filter schema
according to contract A
Filter schema
according to contract B
API schema
Contract schema A
Contract schema B

What are contracts for?

You usually create a contract to support a contract gateway or contract documentation (or both).

Contract gateways

You can deploy a managed instance of your gateway that uses a contract schema. Developers who use this contract gateway can only execute GraphQL operations that the contract schema supports:

Standard gateway
Contract gateway
(All subgraphs)
Admin app
User app

This enables you to hide experimental types and fields that are still in development, or to limit a particular audience's access to only the portions of your graph that they need.

Contract gateways can safely connect to the same subgraph instances as any other gateway, because they can only interact with data that's represented in the contract schema. This does not affect internal routing (e.g. usage of hidden fields in @requires selection sets). Additionally, any @tag labels that are part of the source variant's supergraph schema are preserved in a contract supergraph schema.

Contract documentation

In Studio, each contract variant has its own README, schema reference, and Explorer. If you make a contract variant public, you can provide these resources to external client developers to help them interact with a specific portion of your graph (while omitting irrelevant types and fields).

Setup

1. Update your gateway and subgraphs

Before you create any contracts:

  1. Update your gateway's @apollo/gateway library to version 0.34 or later.
  2. Update your Apollo Server subgraphs to use version 0.1.1 or later of the @apollo/subgraph library.
    • @apollo/subgraph recently replaced @apollo/federation for Apollo Server instances acting as subgraphs. Symbol names are unchanged.
  3. If you're still using the Apollo CLI to register subgraph schemas (via apollo service:push), install the Rover CLI and begin using rover subgraph publish instead.

Older versions of the above libraries and tools don't fully support the required @tag directive.

2. Enable variant support for @tag

A contract uses one of your graph's existing variants (called the source variant) to generate its contract schema. You need to enable the source variant's support for the @tag directive in Apollo Studio.

Open your graph's Settings page and find the Manage Variants section:

Edit supported directives in Studio

Click Edit Build Configuration for the variant you want to use as a source variant, and enable support for @tag.

3. Add @tags

With contracts, you apply tags to types and fields in your subgraph schemas to indicate whether to include or exclude them from your contract schema.

For example, let's take a look at this Products subgraph schema:

products.graphql
# You must include this definition in any schema with tags!directive @tag(name: String!) repeatable on  | FIELD_DEFINITION  | INTERFACE  | OBJECT  | UNION
type Query {
  topProducts: [Product!]!
}

# All fields of the Product object type automatically inherit
# the "partner" tag so we can avoid tagging them individually
type Product @key(fields: "upc") @tag(name: "partner") {
  upc: ID!
  name: String!
  description: String!
  # These fields also inherit the "partner" tag. You can  # prevent access to them by defining an excludes filter in Studio  internalId: ID! @tag(name: "internal")  percentageMatch: Float! @tag(name: "experimental")}

This schema applies the @tag directive to one object (Product) and two object fields (internalId and percentageMatch).

Each tag has a string name. You tag types and fields with the same name if they should be included or excluded as a group by a particular contract.

Whenever your source variant's supergraph schema is generated, that schema retains all of the @tags from your subgraph schemas.

Tagging rules

  • You can apply tags to the following in your schema:
    • Fields of object types (as shown above)
    • Definitions of object, interface, and union types
  • Tag names can include alphanumeric characters (a-z, A-Z, 0-9), along with hyphen (-) and forward slash (/).
  • Whenever you tag an object type definition, also tag every field that returns that type.
    • If you don't do this, a contract might exclude a type while including fields that return it. This produces an invalid contract schema.

Additional guidance is provided in Special cases.

4. Register updated subgraph schemas

After you're done adding tags, update your source variant by registering your updated subgraph schemas to Apollo Studio.

After registering, if Studio doesn't reflect the the tags that you've added in your subgraphs schemas, make sure you've updated all required libraries and tools. If you obtain your subgraph schemas via introspection, older subgraph libraries might strip the @tag directive.

Now you're ready to create your first contract!

5. Create a contract

Open your graph's Settings page and find the same Manage Variants section where you added support for the @tag directive. Below your list of registered schemas, you'll see a Contracts section.

Click Create Contract to open the following dialog:

Create contract dialog

Basic details

In the first step of the dialog, provide the following:

  • A name for your new contract variant
  • The source variant to use

You can't change these values after the contract is created.

Then click Continue.

Contract filters

Next, you specify tag-based filters for your contract:

Create contract dialog

The dialog detects all tag names that are used in your source variant's schema, and it populates its dropdown lists with those names. You can add any number of tag names to each list.

You can also add tag names that are not yet present in your source variant's schema. If you later add tags with that name, the contract honors them.

Your contract will filter types and fields from its source variant according to the following rules:

  • If the Included Tags list is empty, the contract schema includes each type and field unless it's tagged with an excluded tag.
  • If the Included Tags list is non-empty, the contract schema excludes each type and field unless it's tagged with an included tag.
    • The contract schema excludes a type or field if it's tagged with both an included tag and an excluded tag.

When you're done adding tag names, click Continue.

Review and launch

You can now review all of the details of your contract:

Create contract dialog

If everything looks right, click Create. This kicks off the generation of your contract variant and its initial contract schema as a launch.

Studio might encounter an error while generating your contract schema. For descriptions of these errors, see Contract errors.

6. Use your new contract variant

Congratulations! You've created a contract in Apollo Studio. You can now use your contract variant to provide a contract gateway or contract documentation to your users.

For example, you can complete the managed federation setup for a new gateway instance that uses your contract variant.

Automatic updates

Apollo automatically updates your contract schema whenever any of the following occurs:

  • Your contract's source variant successfully composes an updated API schema.
  • You edit your contract.

This makes sure that your contract schema reflects the latest version of your source variant's schema, and that the correct types and fields are included and excluded.

Updates to your contract schema are automatically fetched by your managed contract gateways.

Editing a contract

After you create a contract, you can edit its lists of included and excluded tags. From the Contracts list in your graph's Settings page, click Edit Contract where shown:

Edit contract menu

This opens a dialog similar to the one you used to create the contract.

You can't change an existing contract's name or source variant. Instead, you can create a new contract (and delete the existing contract variant if you no longer need it).

Contract errors

Whenever Apollo Studio attempts to create or update your contract schema, it might encounter an error. Errors are identified by the step in the creation process where they occurred:

ErrorDescription
ADD_DIRECTIVE_DEFINITIONS_IF_NOT_PRESENTAn error occurred adding directive definitions for @tag, @inaccessible, and core directive usages.
DIRECTIVE_DEFINITION_LOCATION_AUGMENTINGAn error occured augmenting the directive definition for @tag to support OBJECT, FIELD_DEFINITION, INTERFACE, and UNION.
EMPTY_OBJECT_AND_INTERFACE_MASKINGAll of an object or interface type's fields were excluded, and an error occurred while excluding the entire type.
EMPTY_UNION_MASKINGAll of a union type's included types were excluded, and an error occurred while excluding the entire union.
INPUT_VALIDATIONThe contract is attempting to include and exclude the same tag.
PARSINGAfter including and excluding fields, the resulting contract schema failed to parse.
PARSING_TAG_DIRECTIVESStudio encountered an error while trying to obtain all uses of @tag from the source variant schema.
PARTIAL_INTERFACE_MASKINGAn interface field's return type was excluded, and an error occurred while excluding that interface field.
SCHEMA_RETRIEVALStudio encountered an error while retrieving the source variant's schema. It might not yet have a valid composed schema.
TAG_INHERITINGStudio encountered an error while attempting to add parent tags to fields.
TAG_MATCHINGStudio encountered an error determining which types and fields should be inaccessible based on their tags.
TO_API_SCHEMAStudio encountered an error while attempting to generate an API schema from the contract variant's supergraph schema.
TO_FILTER_SCHEMAStudio failed to generate and return a contract supergraph schema for an unknown reason.
UNKNOWNAn unknown error occurred.
VERSION_CHECKThe Federation version used is not supported by contracts.

Special cases

  • If a contract excludes every field of a particular object type, the entire type definition is excluded from the contract schema.

  • If a contract excludes an object, interface, or union type, it must also exclude all schema fields that return that type. Otherwise, generation of the contract schema fails.

  • If a contract excludes an object that implements an interface or is included in a union:

    • The contract is not required to exclude schema fields that return that interface or union.

    • However, if a subgraph resolves one of these fields by returning the excluded object, a runtime error occurs in the gateway and the operation fails.

  • You can exclude object fields that are used in a computed field's @requires directive without causing runtime errors.

  • Tags on objects and interfaces (including tags on extension types) are inherited by all fields of that type

  • Tagging interface fields in Federation v1 is not supported. You may still make a field inaccessible by tagging the interface or by ensuring object fields that implement the interface field are removed

Edit on GitHub