Robust GraphQL mutations the Relay way
Tags: graphql, relay
Published: 2020-02-10 13:57:12

---
title: Robust GraphQL mutations the Relay way
published: true
date: 2020-02-06 15:30:35 UTC
tags: graphql,relay
canonical_url: https://blog.logrocket.com/robust-graphql-mutations-the-relay-way/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/njpm4t0zeys3h6fxb924.png
---
**Written by [David Chanin](https://blog.logrocket.com/author/davidchanin/)**✏️

When you are first learning about GraphQL, there’s a few basic traps you may fall into related to API design for mutations that can come back to bite you later on.

Fortunately, if you follow a few simple principles when designing your GraphQL mutations, you’ll be in great shape.

In this article, we’ll look through the [Relay API spec for mutations](https://relay.dev/docs/en/graphql-server-specification#mutations) by Facebook and walk through best practices to follow for your mutations (whether or not you use Relay on the frontend).

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

### Use a unique output type for each mutation

At first, it seems intuitive to have mutations on a resource just directly return that resource in GraphQL.

However, this leads to brittle mutations that cannot expand to add metadata to responses or other resources as your needs change.

Instead, Relay recommends that every mutation have its own unique output type with the suffix `Payload`.

For example, if you have a mutation called `CreateUser`, its output type would be called `CreateUserPayload`.

Let’s make this clearer by looking at an example.

Let’s imagine we’re building a simple blog API.

At first, you may be tempted to make a `CreatePost` mutation that looks like this:

```jsx
mutation CreatePost(title: String!, body: String!): Post
```

This looks simple enough: our mutation just takes a title and body and directly returns a `Post` object.

The problem comes later when we realize we would also like to add the current viewer object to refresh the list of posts on the viewer’s home screen as well.

Currently, there’s no way to add more fields to this output, because the output type is `Post`, which is likely used in lots of other places.

By not using a unique output type for this mutation, the output of the mutation is locked to whatever the fields in `Post` are.

Let’s look at this same mutation using a Relay-style output type.

Now, our mutation looks like this:

```jsx
mutation CreatePost(title: String!, body: String!): CreatePostPayload!

type CreatePostPayload {
  post: Post
}
```

Using a Relay-style output type makes it easy to add more fields to the output.

If we want to add the current viewer, we could add it like so:

```jsx
mutation CreatePost(title: String!, body: String!): CreatePostPayload!

type CreatePostPayload {
  post: Post
  viewer: Viewer!
}
```

This would allow us to send a mutation like this:

```jsx
mutation {
  createPost(title: "My New Post", body: "New Post Body") {
    post {
      id
      name
      body
    }
    viewer {
       dashboardPosts {
         id
         name
       }
    }
  }
}
```

Likewise, if we want to add more fields to the mutation response, there’s no problem – this mutation is future-proof!

### Use a single, unique input-type for each mutation

While it’s not as essential as having a single, unique output-type for each mutation, it’s also a best practice to have a single input parameter called `input` for each mutation.

For Relay, this parameter is indicated with the name of the mutation and the suffix `Input`.

As your mutations get larger and larger and accept more and more parameters, it can quickly become difficult to keep client GraphQL in sync during development.

Moving a large parameter list into an input object like this is known as the [Parameter Object Pattern](http://wiki.c2.com/?ParameterObject), and can help simplify your code.

For example, for our `CreatePost` mutation above, we can rewrite the input using a `CreatePostInput` type like this:

```jsx
mutation CreatePost(input: CreatePostInput!): CreatePostPayload!

type CreatePostInput {
  title: String!
  body: String!
}
```

This lets us use our mutation like this:

```jsx
mutation createPost($input: CreatePostInput!) {
  createPost(input: $input) {
    post { ... }
  }
}
```

Now, no matter how many more fields we add to the `createPost` mutation, the above GraphQL is still correct.

### Idempotent mutations with clientMutationId

One of the stranger parts of the Relay mutation spec is the parameter `clientMutationId`, which shows up in both input and output types for mutations.

This parameter is very powerful though, since it allows your mutations to be made idempotent.

For example, imagine in our above example that a client sends a `createPost` request, but they lose Internet for a moment during the request. How can the client tell if the request went through?

Should it retry again when it gets network access again? If we send another request, but the server did receive the previous request, we’ll end up with a duplicate post.

Fortunately, we can solve this with the `clientMutationId` parameter.

This requires both the client and the server to be aware of this parameter. It allows our server to, for instance, cache the response for each client based on the `clientMutationId` they sent.

So, if the server sees two requests with the same `clientMutationId`, it will realize that the second request is a duplicate and return the cached response again without reapplying the content of the mutation.

This allows the client to get the response content it needs, without accidentally causing the mutation to run multiple times on the server.

By using this parameter, we’ve essentially made all of our mutations idempotent.

The Relay spec also requires sending the same `clientMutationId` back to the client in the output of the mutation.

This is to help clients ensure the response they’re getting is for the mutation they requested in cases where there may be multiple similar mutations sent in quick succession.

### Use a verb for mutation names

While not strictly enforced by Relay, the spec recommends naming your mutations using a verb.

Mutations take an action in your API, so it makes sense to use an active word to indicate that some change will occur by calling the mutation.

For example, you should name a mutation with a verb like `createPost` rather than with a noun like `postCreation`.

### Standardized implementation

An additional benefit of sticking with the Relay spec for mutations is that, as a common spec for GraphQL, it’s easy to implement.

Most common GraphQL libraries have support for Relay, like [Graphene for Python](https://docs.graphene-python.org/en/latest/relay/), or [graphql-js](https://github.com/graphql/graphql-relay-js) for Node/JavaScript.

These libraries make implementing the patterns described above easy, so you don’t need to worry about remembering to create separate named input and output types for each mutation or adding an optional `clientMutationId` param.

It’s still up to you to make your code aware of `clientMutationId` if you’d like to use it, though.

### Conclusion

Relay is a good spec to follow for designing your GraphQL API even if you use Apollo or another GraphQL client on the frontend.

It’s officially supported by Facebook, the creator of both GraphQL and Relay.

They’re industry standards, and the design opinions Relay imposes on mutations will help to ensure your mutations are robust and future-proof as your API grows.

Happy mutating!

* * *
## 200's only ‎✅: Monitor failed and show GraphQL requests in production 

While GraphQL has some features for debugging requests and responses, making sure GraphQL reliably serves resources to your production app is where things get tougher. If you’re interested in ensuring network requests to the backend or third party services are successful, [try LogRocket.](https://www2.logrocket.com/signup-lr)

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/jd2amkhuiynfjf3i33qk.png)

[LogRocket](https://www2.logrocket.com/signup-lr) is like a DVR for web apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic GraphQL requests to quickly understand the root cause. In addition, you can track Apollo client state and inspect GraphQL queries' key-value pairs.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. [Start monitoring for free.](https://www2.logrocket.com/signup-lr)
* * *

The post [Robust GraphQL mutations the Relay way](https://blog.logrocket.com/robust-graphql-mutations-the-relay-way/) appeared first on [LogRocket Blog](https://blog.logrocket.com).