/ ruby

Introduction to GraphQL mutations

In the previous post we learned about the basics of GraphQL and the mutations were left out.

This is because mutations are a different beast from object types.

What are mutations?

Mutations are the way to make a GraphQL call that will save, update or destroy a data in our server, therefore mutating our data.

Think in mutations as the POST, PUT, PATCH, DELETE endpoints of a REST API.

The difference here is that you send a mutation and specify what you want back, in other words, perform a mutation followed by a query in one API hit.

That is the same inversion that GraphQL has for queries, the client specifies what he needs back and not the opposite.


See an example of creating a product:

mutation {
  createProduct(input: {name: "iPhone 7", price: 649.0}) {

The response may be similar to:

  "data": {
    "createProduct": {
      "id": "42",
      "name": "iPhone 7",
      "price": 649

The difference from query calls is that you need to wrap the mutation in a mutation block because all GraphQL calls are implicitly wrapped in a query block unless you specify otherwise.

To implement a mutation in graphl-ruby, you need to implement the mutation:

# app/graphql/mutations/create_product.rb
Mutations::CreateProduct = GraphQL::Relay::Mutation.define do
  name "CreateProduct"

  input_field :name, !types.String
  input_field :price, !types.Float

  return_type Types::ProductType

  resolve ->(obj, args, ctx) {
      name: args[:name],
      price: args[:price]

Tip: Using an exclamation makes the input field required.

Pretty similar to Object Types with the difference that you specify the input fields and the return type.

This means that you are supposed to return a product on the resolve block and that product will be passed to the Types::ProductType, therefore allowing the client to specify the response shape of that product type.

And then you need to specify the entry point on your mutation type:

Types::MutationType = GraphQL::ObjectType.define do
  name "Mutation"

  field :createProduct, Mutations::CreateProduct.field

Do not confuse the mutation with the mutation type.

A mutation implements the mutation algorithm whereas mutation type specifies the mutation "endpoints".

The mutation type is pretty similar to the query type, the difference is that you specify, as you guessed, the mutation endpoints.


As you may already know, you can specify more than one query for the same GraphQL call.

That's also true for mutations, you are able to perform multiple updates in one call:

mutation {
  account: updateAccount(input: {name: "Gabriel Sobrinho"}) {

  product: updateProduct(input: {id: 42, price: 769}) {
    comments(order: "mostRecent", limit: 10) {

All the benefits of reading apply as well, you may use a different response shape for mobile application and a denser response shape for desktop applications.

All the cons apply as well, be sure to read my previous post to understand them.