2. What is a mutation?

🖋 GraphQL operations

So far, our app has only used one type of GraphQL operation: queries. These are read-only operations to retrieve data. To modify data, we need to use another type of GraphQL operation: mutations, which are write operations.

Much like the Query type, the Mutation type serves as an entry point to our schema. It follows the same syntax as the schema definition language, or SDL, that we've been using so far.

✍️ Schema syntax

We declare the Mutation type using the type keyword, then the name Mutation. Inside the curly braces, we have our entry points, the fields we'll be using to mutate our data.

Illustration showing the schema syntax for adding a mutation

We recommend starting with a verb that describes the specific action of our update operation (such as add, delete, or create), followed by whatever data the mutation acts on. Because mutations typically modify a specific object, they often require arguments. We can add arguments as needed, following the same SDL syntax. The return type of the mutation comes after the colon.

For the mutation response, we should return the data that the mutation updated, so that our client can update its UI without having to run a followup query.

Which of these are good names for mutations based on the recommended conventions above?

🤔 Modifying multiple objects

When a mutation updates more than just one object, how do we pick which one to return?

To answer that question, let's look at an example schema with spacecats and missions.

Illustrating showing the schema syntax for spacecats and missions

A spacecat has a list of missions they've been assigned to. A mission can also have more than one spacecat assigned to it, like a crew. We want to create a mutation called assignMission that assigns one spacecat to a particular mission. This would update that spacecat's list of missions, and it would also update a mission's list of crew members.

So which type should our mutation return? SpaceCat? Or Mission?

We'll want to return both, because our client might need both.

In addition, we'll need to account for any partial errors that might occur and return helpful information to the client. We recommend adding three common fields to all mutation responses:

  • code: an Int that refers to the status of the response, similar to an HTTP status code.

  • success: a Boolean flag that indicates whether all the updates the mutation was responsible for succeeded.

  • message: a String to display information about the result of the mutation on the client side. This is particularly useful if the mutation was only partially successful and a generic error message can't tell the whole story.

Illustration showing the fields on the mutation type and the fields the response should include

Which of these are reasons to create a separate object for a mutation's return type?

Circling back to the assignMission mutation, we're going to create a new type specifically for its response. By convention, this return type will start with the name of the mutation (AssignMission) and end with Response. This type will contain the three informational properties, as well as additional fields for each object that the mutation updated.

Illustration showing the new AssignMissionResponse return type

Mutations vs Queries

Queries and mutations are both types of GraphQL
. Queries are
operations that always
data. Mutations are
operations that always
data. Similar to Query fields, fields of the
type are also
into a GraphQL API.

Drag items from the box to the blanks above

entry points

That's the basics of what we need to know about mutations! Let's dive into the code and add our first mutation to the schema.