Topik wawancara representatif

Wawancara Backend: Bagaimana Anda merancang batch API dengan partial failure?

BackendSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Anda memerlukan API pembaruan batch yang menerima hingga 1.000 sumber daya per permintaan. Beberapa item mungkin gagal dalam validasi, otorisasi, atau dependensi sementara. Bagaimana Anda merancang permintaan, respons, idempotensi, retry, dan observabilitas agar klien tidak salah mengira keberhasilan parsial sebagai keberhasilan penuh?

Konteks dan cakupan

Pertanyaan ini menguji apakah seorang backend engineer dapat memberikan semantik eksekusi dan hasil yang presisi pada proses "batch". Asumsikan pelanggan ingin memperbarui label pesanan atau pengaturan pengguna secara massal; item dapat bersifat independen atau berbagi kuota, versi, atau dependensi, dan batas waktu jaringan (timeout) dapat terjadi setelah server menyelesaikan beberapa item. Anda harus menentukan batas sinkron dan asinkron agar klien dapat melanjutkan proses dengan aman.

Topik ini cocok untuk backend engineer, perancang API, dan platform engineer. Fokuslah pada atomisitas, status per item, identitas permintaan, retry yang idempoten, otorisasi dan batas sumber daya, kompatibilitas respons, serta pemulihan daripada pilihan spesifik REST, gRPC, atau antrean. Nyatakan perilaku default, bagaimana partial success dipilih secara eksplisit, dan perbedaan antara kegagalan total, kegagalan parsial, dan hasil yang tidak diketahui.

Apa yang dinilai oleh pewawancara

Jawaban yang kuat akan menanyakan apakah item saling bergantung sebelum memilih pemrosesan atomik, partial success berbasis opt-in, atau operasi asinkron. Jawaban tersebut tidak hanya mengembalikan HTTP 200 dan jumlah kegagalan; melainkan memetakan setiap input ke hasil yang stabil, kelas kesalahan, dan kemampuan retry. Google AIP-234 mencatat bahwa mengubah metode batch sinkron yang sudah ada menjadi partial success dapat merusak klien dan merekomendasikan status kegagalan per-indeks yang terperinci; panduan idempotensi Stripe mengikat retry ke parameter yang sama dan mempertahankan hasil pertama. Cakup juga batasan, audit, dan pemantauan.

Pertanyaan klarifikasi yang perlu diajukan

  • Apakah ada dependensi urutan atau transaksional antar-item? Apakah bisnis harus bersifat all-or-nothing?
  • Apakah pemrosesan menimbulkan efek samping eksternal, dan dapatkah idempotency key membuat pemutaran ulang (replay) menjadi aman?
  • Apakah klien memerlukan hasil sinkron, atau dapatkah klien menerima sebuah operasi lalu melakukan polling atau berlangganan ke progres?
  • Apa saja persyaratan batas batch, ukuran body, batas waktu (timeout), kuota tenant, dan keadilan (fairness)?
  • Kesalahan mana yang dapat di-retry, mana yang memerlukan perubahan input, dan bagaimana hasil yang tidak diketahui dapat di-query?

Kerangka jawaban 30 detik

“Saya akan memisahkan batch atomik dari batch partial-success dan menetapkan perilaku yang lebih aman sebagai default; partial success hanya diaktifkan jika klien memilihnya (opt-in) dan bisnis mengizinkannya. Setiap input mendapatkan indeks yang stabil atau ID permintaan klien, sementara server mencatat status idempotensi tingkat batch dan tingkat item, hasil, serta kelas kesalahan. Pekerjaan sinkron dibatasi; pekerjaan yang lebih besar membuat operasi yang berjalan dalam pecahan (shards) dan mengekspos progres. Respons membedakan keberhasilan, kegagalan permanen, kegagalan sementara, dan status tidak diketahui, dan retry menggunakan kembali kunci item yang sama. Saya akan memvalidasi desain tersebut dengan rate limit, catatan audit, metrik, dan fault injection untuk membuktikan bahwa efek samping tidak terduplikasi atau hilang.”

Jawaban langkah demi langkah

Langkah 1: Pilih model atomisitas

Jika item berbagi invarian bisnis yang tidak dapat dipisahkan, seperti kedua sisi transfer yang harus berhasil bersamaan, gunakan transaksi batch atomik atau tolak antarmuka batch. Jika item bersifat independen, pertimbangkan partial success. Jangan menyembunyikan model di balik "best effort"; klien harus mengetahui apakah semua berhasil, semua gagal, sebagian selesai, atau server tidak dapat mengonfirmasi hasilnya.

Langkah 2: Tentukan identitas permintaan dan item

Sertakan ID batch, array item, dan ID permintaan item yang dihasilkan klien. ID item bersifat stabil dalam cakupan bisnisnya. Pengiriman duplikat dengan ID yang sama harus membandingkan parameter penting; parameter yang berbeda harus menghasilkan konflik alih-alih penimpaan diam-diam (silent overwrite). ID batch mendukung pelacakan (tracing) tetapi tidak dapat menggantikan idempotensi item karena retry parsial mungkin hanya berisi item yang gagal dari batch asli.

Langkah 3: Tetapkan batas sinkron/asinkron

Batch kecil dapat mengembalikan hasil akhir per item secara sinkron, dengan total anggaran waktu dan sumber daya. Batch besar atau operasi yang memanggil sistem eksternal harus mengembalikan ID operasi, dieksekusi dalam shard yang dibatasi, dan menyimpan progresnya secara persisten. Klien meng-query jumlah item yang selesai, sedang diproses, dapat di-retry, dan kegagalan permanen; setelah terputus, klien melakukan query alih-alih memulai kembali efek samping.

Langkah 4: Rancang respons yang dapat diparsing

Respons harus memungkinkan klien menemukan hasil berdasarkan identitas input, bahkan jika server mengubah urutan pekerjaan. Gunakan indeks stabil dan ID klien; sertakan kode kesalahan yang dapat dibaca mesin, kemampuan retry, kemungkinan perubahan status saat retry, dan pesan pengguna yang aman. Sebagai contoh:

json
{
  "batch_id": "b_123",
  "status": "PARTIAL",
  "results": [
    {"index": 0, "request_id": "r_0", "status": "SUCCEEDED"},
    {"index": 1, "request_id": "r_1", "status": "FAILED", "error": {"code": "VERSION_CONFLICT", "retryable": false}}
  ],
  "next_page_token": null
}

Google AIP-234 merekomendasikan peta failed_requests dari indeks input ke status terperinci untuk pembaruan batch asinkron. Hal ini menghindari keharusan bagi klien untuk memelihara pemetaan ID-permintaan-ke-permintaan dan menghindari pengulangan isi permintaan (body) yang sensitif. Jika API sinkron yang ada memerlukan semantik partial-success, rilis versi baru atau lakukan negosiasi dengan kolom eksplisit sehingga klien lama tidak menafsirkan status sukses sebagai penyelesaian setiap item.

Langkah 5: Tangani idempotensi, retry, dan hasil yang tidak diketahui

Server dapat menolak parameter yang tidak valid sebelum efek samping dimulai tanpa menyimpan hasil idempoten. Setelah eksekusi dimulai, simpan hasil atau status in-progress yang dapat di-query. Setelah terjadi timeout jaringan, klien tidak boleh menebak dan mengulangi seluruh batch; klien menggunakan kembali kunci batch dan item, meng-query item yang tidak diketahui, dan me-retry hanya item yang jelas dapat di-retry. Gunakan backoff dan jitter untuk kesalahan sementara, wajibkan perubahan input untuk kesalahan permanen, dan kembalikan konflik ketika kunci yang digunakan kembali membawa parameter yang berbeda.

Langkah 6: Isolasi sumber daya dan pengurutan

Bagi pekerjaan ke dalam shard yang dibatasi dan batasi konkurensi per tenant, batch, dan dependensi. Eksekusi item yang saling bergantung berdasarkan topologi atau fase eksplisit; jalankan item independen secara paralel dengan anggaran retry bersama untuk mencegah badai kegagalan (failure storm). Periksa otorisasi dan kuota sebelum setiap item, sehingga endpoint batch tidak dapat melewati kebijakan API item tunggal.

Langkah 7: Tentukan semantik kesalahan, pembatalan, dan pemulihan

Klasifikasikan kesalahan validasi input, otorisasi, konflik versi, kuota, dependensi sementara, dan hasil yang tidak diketahui. Pembatalan menghentikan item yang belum dimulai; efek samping yang telah selesai tidak dapat berpura-pura di-rollback. Jika bisnis memerlukan pembalikan, sediakan operasi kompensasi terpisah. Simpan tugas latar belakang, hasil, dan permintaan asli secara persisten sehingga proses restart melanjutkan dari status item daripada mengeksekusi setiap item kembali.

Langkah 8: Verifikasi konsistensi dan visibilitas operasional

Uji skenario semua berhasil, semua gagal, hasil campuran, permintaan duplikat, konflik parameter, timeout lalu query, dependensi yang tidak stabil (flapping), race condition pembatalan, dan restart worker. Pantau keberhasilan batch, kelas kesalahan per item, status tidak diketahui, amplifikasi retry, usia antrean, latensi pemrosesan, penolakan kuota, dan pengiriman duplikat. Lakukan audit pada batch, item, aktor, keputusan otorisasi, dan hasil akhir sehingga staf pendukung dapat menjelaskan dengan tepat item mana yang telah selesai.

Pertukaran desain (trade-off) dan batasan

Partial success tidak secara otomatis menjadi pilihan yang lebih canggih. Ini cocok untuk item independen yang dapat diperbaiki pelanggan satu per satu; saldo, inventaris, dan invarian lintas sumber daya lebih aman dengan atomisitas atau alur kerja eksplisit. HTTP 207 Multi-Status dapat membawa beberapa status sumber daya, tetapi RFC 4918 mendefinisikannya untuk WebDAV. API JSON umum tidak boleh berasumsi bahwa klien memahami hasil parsial hanya karena mengembalikan kode 207. Tempatkan semantik item dalam body respons yang stabil dan pilih kode status dengan mempertimbangkan kompatibilitas klien yang sudah ada.

Kapan Anda harus memilih atomic batch?

Pilih atomisitas ketika kegagalan satu item membuat status agregat menjadi tidak valid atau kompensasi tidak dapat diterima. Gunakan transaksi, preflight, atau alur kerja, sambil menyadari bahwa pekerjaan yang di-shard dan efek samping eksternal tidak berbagi transaksi database yang sama; proses tersebut mungkin memerlukan fase cadangan (reserve), commit, dan kompensasi.

Kapan Anda harus memilih operasi asinkron?

Kembalikan sebuah operasi ketika durasi tidak dapat diprediksi, ukuran batch besar, melibatkan panggilan eksternal, atau klien tidak boleh menahan koneksi tetap terbuka. Statusnya harus dapat di-query ulang, dan hasilnya harus memiliki paginasi. Progres tidak boleh menyebut status "diterima" (accepted) sebagai "selesai" (completed).

Latihan kegagalan dan rencana evolusi

Lakukan uji coba (pilot) dengan kumpulan tenant terbatas, catat status item dan perilaku retry, lalu tingkatkan batas batch secara bertahap. Injeksikan pemutusan jaringan setelah item ke-30 berhasil, dependensi yang mengembalikan 503 terus-menerus, kunci yang sama dengan parameter berbeda, dan restart pada worker operasi. Perluas kuota atau aktifkan partial success hanya setelah klien dapat meng-query hasil yang tidak diketahui dan server terbukti tidak menduplikasi efek samping.

Bagaimana Anda mengembangkan API sinkron menjadi partial success?

Pertahankan semantik atomik versi lama dan tambahkan versi baru yang mengembalikan operasi serta kegagalan per item. Sebagai alternatif, wajibkan kolom return_partial_success yang eksplisit dan pertahankan perilaku lama jika kolom tersebut tidak ada. Dokumentasikan kode status, kolom respons, aturan retry, dan tanggal penghentian (deprecation) sehingga klien tidak mengubah interpretasinya secara diam-diam.

Bagaimana Anda mengevaluasi kebenaran implementasi klien?

Amati apakah klien menyimpan ID item secara persisten, me-retry hanya kegagalan yang dapat di-retry, meng-query hasil yang tidak diketahui, serta menghindari efek samping duplikat dan retry yang tidak valid. Sediakan helper pengurai (parsing) dan query di SDK utama, sementara server tetap menoleransi kolom yang tidak dikenal dan permintaan duplikat.

Kesalahan umum dan tindak lanjut

Mengembalikan HTTP 200 dengan jumlah kegagalan

Klien lama dapat memperlakukan penyelesaian parsial sebagai selesai penuh, dan tetap tidak dapat mengetahui item mana yang harus di-retry. Respons memerlukan status keseluruhan, identitas item, kelas kesalahan, dan tindakan berikutnya.

Me-retry seluruh batch pada kegagalan apa pun

Hal itu dapat mengulangi efek samping yang sudah berhasil. Query status idempotensi batch dan item terlebih dahulu, retry hanya kesalahan sementara yang eksplisit, dan gunakan ID permintaan bisnis yang baru ketika parameter berubah.

Bagaimana hasil harus diurutkan?

Hubungkan hasil berdasarkan indeks input atau ID permintaan yang stabil, bukan urutan penyelesaian. Pertahankan identitas tersebut saat hasil dipaginasi sehingga klien dapat menggabungkan halaman dengan aman.

Bisakah Anda melakukan rollback setelah satu item berhasil dan batch dibatalkan?

Pembatalan hanya memengaruhi item yang belum dimulai. Efek samping eksternal yang telah dibuat memerlukan API kompensasi atau penanganan manual; status "batch dibatalkan" bukanlah jaminan rollback.

Bagaimana Anda mencegah endpoint batch melewati otorisasi?

Periksa izin tenant dan operasi di tingkat batch, lalu periksa kembali kepemilikan sumber daya, versi, dan izin kolom sebelum memproses setiap item. Batching mengubah penjadwalan, bukan cakupan otorisasi.

Bagaimana Anda menjelaskan kegagalan parsial akhir?

Sediakan ID batch yang dapat diaudit, ID item, status, kode kesalahan, kemampuan retry, dan stempel waktu. Berikan penjelasan bisnis yang aman kepada tim dukungan dan simpan kesalahan trace serta dependensi untuk diagnosis rekayasa (engineering).

Sumber publik

Pertanyaan terkait