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 mutation keyword — it cannot be omitted like query.
  • 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.

Leave a Comment