GraphQL Mutations – Writing Data
A mutation is how you create, update, or delete data in GraphQL. While queries read data without changing anything, mutations intentionally change the state on the server. Every write operation — signing up a user, placing an order, deleting a record — uses a mutation.
Mutations vs Queries — The Core Difference
Query Mutation ───── ──────── Reads data only Changes data on the server Safe to run multiple times Has side effects Fields run in parallel Fields run one at a time, in order Keyword: query (or omit it) Keyword: mutation (required)
Writing a Basic Mutation
Schema:
────────
type Task {
id: ID!
title: String!
completed: Boolean!
}
type Mutation {
createTask(title: String!): Task!
}
Client mutation:
─────────────────
mutation AddTask {
createTask(title: "Buy groceries") {
id
title
completed
}
}
Response:
──────────
{
"data": {
"createTask": {
"id": "task_77",
"title": "Buy groceries",
"completed": false
}
}
}
Notice that a mutation returns data just like a query. You specify which fields to receive from the newly created or modified object. This avoids a separate follow-up query to confirm the change.
Update Mutation
Schema:
────────
type Mutation {
updateTask(id: ID!, completed: Boolean!): Task!
}
Mutation:
──────────
mutation FinishTask {
updateTask(id: "task_77", completed: true) {
id
title
completed
}
}
Response:
──────────
{
"data": {
"updateTask": {
"id": "task_77",
"title": "Buy groceries",
"completed": true ← Server confirms the change
}
}
}
Delete Mutation
Delete mutations usually return either the deleted object or a simple boolean confirming success.
Schema:
────────
type Mutation {
deleteTask(id: ID!): Boolean!
}
Mutation:
──────────
mutation RemoveTask {
deleteTask(id: "task_77")
}
Response:
──────────
{
"data": {
"deleteTask": true
}
}
Multiple Mutations Execute in Order
When you include multiple mutation fields in one request, GraphQL runs them one after another in the order you wrote them. This prevents race conditions when mutations depend on each other.
mutation SetupProject {
createProject(name: "Website Redesign") {
id ← Runs first
}
assignOwner(projectId: "p1", userId: "u5") {
projectName ← Runs second (after createProject finishes)
}
}
This sequential execution is the opposite of queries, where fields run in parallel. It matters when step two depends on step one completing successfully.
Mutations Can Fail Partially
If one mutation in a multi-mutation request fails, GraphQL returns an error for that field but still attempts the remaining mutations. Each mutation is independent unless you build transactions into your resolvers explicitly.
Key Points
- Mutations write, update, or delete data on the server.
- Always use the
mutationkeyword — it cannot be omitted likequery. - Mutation fields return data, so you select the fields you want back from the changed object.
- Multiple mutations in one request run sequentially, not in parallel.
- Returning the updated object from a mutation saves a separate follow-up read query.
