GraphQL Mutation Design: Static-Friendly Mutations

Marc-André Giroux
Feb 22, 2018 · 4 min read

This is a new post in my GraphQL Mutation Design series. Last week, we talked about what I called Anemic Mutations. This week, we’re touching a new subject: How to design mutations so that clients can use the power of static queries.

We often talk about how powerful GraphQL Clients are, but sometimes we forget that depending how the GraphQL Schema is designed, thing may be much more awkward on the client side.

Static Queries

Static queries already have a good rep in the GraphQL ecosystem. It’s hard to argue against them since they bring so many advantages to building great clients and apps.

When I say about static queries, I’m talking about GraphQL queries that will always have the same query string no matter what the variables are at runtime. This is done by using GraphQL variables and directives to alter runtime behavior.

There are several advantages to this. Amongst others, this leads to easier code generation to handle these queries, persisted queries, better tooling, and better predictability. I find that Sashko Stubailo did a great job explaining why they’re great a while ago in his post:

When building a GraphQL schema, there’s an important thing that I think we should keep in mind: A client should never have to dynamically build query strings or use a query builder.

Optimizing Mutations for Static Usage

Now that we know how useful building static queries is, we need to make sure we design our schema in a way that clients are not forced to dynamically build their queries.

Let’s take the e-commerce example from the last post:

Image for post

We decided not to use a fat data-centric mutation and use a finer-grained mutation to add an item to our checkout. From a server side perspective, this is pretty great to maintain. However, if we start thinking about clients, especially when it comes to keeping queries static, we quickly see that we might hit problems.

Imagine this scenario: we’re building a shopping cart UI that let’s users build up a cart of items, and when they are ready they may press the checkout button to start the payment process. Easy! Let’s say we don’t care so much about losing the carts so we’ll have our cart in local storage, and then when the user is truly ready, we’ll use addItemToCheckout to commit the items to a checkout.

You might be seeing the problem already. We truly have no way of doing this using a static GraphQL query given this schema design. In fact, if we don’t want to make n network calls, our client might end up having to do something like this:

Image for post

Since the field addItemToCheckout only lets us add a single item to the checkout with a set of variables, we need to use the field n times for n items. And because of that… our client has to build up a dynamic query string to achieve that, a big no when it comes to static queries!

Image for post
This doesn’t look too fun to maintain and understand

Plural arguments, not plural fields

There’s a pretty simple way to enable this use case while keeping our mutation static. As we said earlier, variables are one way to modify our queries at runtime without changing the query string. What if instead of having to use our field n times, we simply passed n variables instead?

Image for post

Now that our input can accept any number of items through items, we can build up a query string that will never change in function of the number of items. Only the variables we send will change:

Image for post
Much nicer to use!


As you can see, even though GraphQL gives power to clients, theres a way to give them an easier time by designing our GraphQL schema the right way.

Now, that doesn’t mean you can never expose a “singular” field in your queries or mutations. What it does mean is that maybe you should expose the plural version too if its a valid use case. In fact, a good example of this are the node and nodes field in Relay, so this is not only for mutations!

Designing mutations is tricky because we need to know our clients very well to make good decisions. I find that by following these guidelines, it makes things just a bit easier.

Thank for reading ❤️ As always, if you’ve enjoyed this post, you could follow me on twitter! In the next post we’ll explore an issue that arrises when we use multiple mutation fields in a single request. Stay tuned!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store