Lesson 10 / 25
Designing Mutations
Input and payload types.
Specific actions, single input, rich payload
Name mutations after business actions (placeOrder, cancelSubscription) rather than generic updateOrder with many optional fields. A common convention uses a single input argument and returns a payload type containing the changed objects (so clients can update their caches) and any user-facing errors. Make mutations idempotent where possible, for example by accepting a client-generated ID or idempotency key for operations such as payments.
Changing data and reporting problems
Well-designed mutations, clear error handling and real-time subscriptions complete the API.
A placeOrder mutation
Schema and a client operation.
input PlaceOrderInput {
cartId: ID!
shippingAddressId: ID!
idempotencyKey: String!
}
type PlaceOrderPayload {
order: Order
userErrors: [UserError!]!
}
type UserError {
field: [String!]
message: String!
code: String!
}
mutation Checkout($input: PlaceOrderInput!) {
placeOrder(input: $input) {
order { id status total { amount currency } }
userErrors { field message code }
}
}Return what changed
Including the updated object with its id lets normalised client caches refresh automatically.
Quick check: Why return the modified object in a mutation payload?
- So clients can update their caches without another request
- Because GraphQL requires exactly one field
- To slow down attackers
- To avoid using variables
Answer
So clients can update their caches without another request — Caches normalise by id.