You're viewing documentation for a version of this software that is in development. Switch to the latest stable version
Launch Apollo Studio

Value types

Define the same type in multiple subgraphs


In Apollo Federation, a value type is any type that's defined in multiple subgraphs but isn't an entity. In the following example, both Position and Color are value types:

# Subgraph A
type Position {
  x: Int!
  y: Int!
}

enum Color {
  RED
  GREEN
  BLUE
}
# Subgraph B
type Position {
  x: Int
  y: Int
}

enum Color {
  CYAN
  MAGENTA
  YELLOW
}

As this example shows, a value type's definition can differ between subgraphs in Federation 2. This is not true in Federation 1.

Whenever a value type definition varies in a valid way, composition generates warnings, but not errors.

This article describes how to define value types in a federated graph, along with scenarios where value type definitions can break composition.

Objects

The fields of an object value type can differ between subgraphs in certain ways:

  • A field's return type can vary in nullability (Int vs. Int!).
    • A field's return type can't vary in its core type (Int vs. String) or in whether it returns a list (Int vs. [Int]).
  • A field can be omitted from a subgraph entirely if that field is always resolvable.

See the following subsections for details.

Varying field return types

Let's say two subgraphs both define an Event object type with a timestamp field:

# Subgraph A
type Event {
  timestamp: Int!}
# Subgraph B
type Event {
  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 definitions.

Next, look at these varying definitions for the Position object type:

# Subgraph A
type Position {
  x: Int!
  y: Int!
}
# Subgraph B
type Position {
  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:

# 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.

Note that Subgraph A's actual subgraph schema is not modified. Within Subgraph A, x and y remain non-nullable.

Omitting fields

Look at these two definitions of a Position object type:

⚠️

# Subgraph A
type Position {
  x: Int!
  y: Int!
}
# Subgraph B
type Position {
  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:

# 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:

# Subgraph A
type Query {
  currentPosition: Position!
}

According to the hypothetical supergraph schema, the following query is valid against the supergraph:

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. So how do we fix it? Check out Solutions for unresolvable fields.

Enums and unions

In Federation 2, enum and union value type definitions can differ between subgraphs:

# Subgraph A
union Media = Book | Movie

enum Color {
  RED
  GREEN
  BLUE
}
# Subgraph B
union Media = Book | Podcast

enum Color {
  CYAN
  MAGENTA
  YELLOW
}

Composition logic merges these definitions in your supergraph schema:

# Supergraph schema
union Media = Book | Movie | Podcast

enum Color {
  RED
  GREEN
  BLUE
  CYAN
  MAGENTA
  YELLOW
}

This can be useful when different subgraphs are responsible for different subsets of a particular set of related types or values.

Edit on GitHub