Belajar GraphQL - Mutations untuk Create, Update, Delete
Episode 5 of 51

Belajar GraphQL - Mutations untuk Create, Update, Delete

Episode 5 membahas mutations untuk menulis data: struktur dan syntax dasar, perancangan input types yang baik, operasi CRUD lengkap, pola response dengan payload, eksekusi serial untuk multiple mutations, hingga best practices penamaan dan idempotensi.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Query memungkinkan kalian membaca data; mutation memungkinkan kalian mengubahnya. Episode 5 membedah mutation secara lengkap: struktur syntax, perancangan input type, operasi create-update-delete, dan pola response yang konsisten.

Kita juga membahas perilaku penting eksekusi serial untuk multiple mutations, serta best practices seperti penamaan, idempotensi, dan validasi di level input. Setelah episode ini, kalian bisa merancang lapisan tulis API GraphQL yang aman dan mudah dipakai.

Struktur Mutation

Syntax Dasar

Mutation ditulis dengan keyword mutation, diikuti operation name, dan seleksi field yang menjadi hasilnya:

Mutation dasar
mutation BuatPost($input: CreatePostInput!) {
  createPost(input: $input) {
    id
    title
    createdAt
  }
}

Dengan variabel yang dikirim terpisah sebagai objek JSON {"input": {...}}:

Variabel mutation
{
  "input": {
    "title": "Belajar GraphQL",
    "body": "Isi postingan pertama"
  }
}

Perbedaan kunci dengan query: mutation mengubah state dan dieksekusi secara serial. GraphQL menjamin field-field mutation dijalankan satu per satu, berurutan, sehingga mutation kedua dalam satu request melihat efek mutation pertama.

Mengembalikan Data Setelah Mutation

Selalu minta data hasil mutation pada response, bukan hanya status. Dengan mengembalikan objek yang dimutasi (seperti id, title, createdAt di atas), client tidak perlu melakukan query tambahan untuk mendapatkan data terbaru — menghilangkan round-trip ekstra.

Input Types untuk Mutations

Merancang Input yang Baik

Input type adalah cara GraphQL menerima data terstruktur untuk mutation. Prinsip desainnya: pindahkan validasi struktur ke level input, sehingga resolver tidak perlu menebak-nebak bentuk data:

Input type yang dirancang baik
input CreatePostInput {
  title: String!
  body: String!
  tags: [String!]
  publishedAt: DateTime
}

Gunakan tipe yang spesifik, tandai field wajib dengan !, dan pisahkan input untuk create dan update seperti di episode 3. Jangan memakai object type untuk menerima data — object type tidak dirancang untuk itu.

Reusable Input Types

Input yang dipakai banyak mutation (misalnya alamat atau kategori) bisa dijadikan satu input type yang dipakai ulang. Ini menjaga konsistensi dan mengurangi duplikasi. Perhatikan bahwa input type bisa bersarang — sebuah input bisa berisi input lain — untuk data yang bertingkat seperti item pesanan.

CRUD Operations

Create, Update, dan Delete

Pola umum untuk setiap entitas adalah empat mutation:

CRUD lengkap untuk entitas Post
type Mutation {
  createPost(input: CreatePostInput!): Post
  updatePost(id: ID!, input: UpdatePostInput!): Post
  deletePost(id: ID!): Post
}

Untuk update, ada dua pendekatan. Full update mengharuskan seluruh field dikirim (cocok untuk form lengkap). Partial update memakai input dengan semua field nullable, seperti UpdatePostInput dengan title: String dan body: String, sehingga hanya field yang diberikan yang diubah — pola ini paling umum dipakai dan bersifat PATCH-style.

Batch Mutations

Untuk membuat atau memperbarui banyak entitas sekaligus, gunakan input bertipe list:

Batch mutation
type Mutation {
  createPosts(input: [CreatePostInput!]!): [Post]
}

Pola ini mengurangi jumlah request dibanding memanggil mutation satu per satu. Perhatikan trade-off-nya: batch besar membuat request lama diproses dan error handling menjadi lebih kompleks, karena sebagian bisa sukses dan sebagian gagal.

Mutation Response Patterns

Payload Pattern

Best practice modern adalah mengembalikan payload object yang membungkus hasil, alih-alih langsung mengembalikan objek:

Payload pattern dengan union
type CreatePostResult {
  post: Post
  errors: [FieldError]
}
 
type FieldError {
  field: String!
  message: String!
}

Dengan payload, kalian bisa mengembalikan data sukses sekaligus error per field dalam satu struktur. Ini menjadi dasar pola yang sangat powerful: result pattern dengan union types, yang akan kita bahas menyeluruh di episode 11. Untuk kesederhanaan awal, kalian bisa mulai dengan mengembalikan objek langsung, lalu berpindah ke payload saat API mulai kompleks.

Optimistic Responses

Di sisi client, optimistic response memungkinkan UI memperbarui tampilan segera sebelum server menjawab, lalu disinkronkan saat response tiba. Ini bukan bagian dari schema, melainkan fitur client — kita akan mengimplementasikannya dengan Apollo Client di episode 25.

Best Practices

Penamaan dan Idempotensi

  • Gunakan kata kerja yang jelas: createX, updateX, deleteX, addTagToPost.
  • Sertakan objek yang terpengaruh: createPost bukan submit.
  • Untuk operasi yang bisa dijalankan berulang tanpa efek ganda, pertimbangkan idempotensi dengan clientMutationId atau idempotency key.
Idempotency key
type Mutation {
  createOrder(input: CreateOrderInput!, idempotencyKey: String!): Order
}

Validasi di level input (episode 10) dan penanganan error yang konsisten (episode 11) adalah dua hal yang wajib ada pada setiap mutation di production.

Penutup

Inti yang harus dibawa pulang:

  • Mutation menulis data, dieksekusi secara serial, dan mengembalikan data hasilnya.
  • Gunakan input type terpisah untuk create dan update; update bersifat partial dengan field nullable.
  • Batch mutation mengurangi round-trip, tapi tingkatkan kompleksitas error handling.
  • Payload pattern membungkus hasil dengan data dan error dalam satu struktur.
  • Beri nama mutation dengan kata kerja yang jelas dan dukung idempotensi.

Di episode 6 selanjutnya kalian akan mempelajari resolvers — jantung GraphQL — mulai dari anatomy fungsi resolver, keempat parameter parent, args, context, dan info, resolver chains, context object, hingga pola async resolver dan organisasi file resolver. Inilah tempat data benar-benar diambil!

Belajar GraphQL - Mutations untuk Create, Update, Delete | Belajar GraphQL