Alur kerja berbasis event vs API request-response untuk tugas jangka panjang
Bandingkan event-driven workflows dengan API request-response untuk proses jangka panjang, fokus pada persetujuan, timer, retry, dan audit trail di aplikasi bisnis.

Mengapa proses jangka panjang rumit di aplikasi bisnis
Sebuah proses disebut “jangka panjang” ketika tidak bisa selesai dalam satu langkah cepat. Bisa memakan menit, jam, atau hari karena bergantung pada orang, waktu, atau sistem luar. Apa pun yang melibatkan persetujuan, serah terima, dan menunggu masuk dalam kategori ini.
Di sinilah pemikiran API request-response sederhana mulai runtuh. Panggilan API dibangun untuk pertukaran singkat: kirim permintaan, dapat jawaban, lanjut. Tugas panjang lebih seperti cerita berbab-bab. Anda perlu berhenti, mengingat tepat di mana Anda berada, dan melanjutkan nanti tanpa menebak.
Anda melihat ini di aplikasi bisnis sehari-hari: persetujuan pembelian yang butuh manager dan bagian keuangan, onboarding karyawan yang menunggu pemeriksaan dokumen, pengembalian dana yang bergantung pada penyedia pembayaran, atau permintaan akses yang harus ditinjau lalu diterapkan.
Ketika tim memperlakukan proses panjang seperti satu panggilan API, beberapa masalah yang dapat diprediksi muncul:
- Aplikasi kehilangan state setelah restart atau deploy dan tak bisa melanjutkan dengan andal.
- Retry menciptakan duplikasi: pembayaran kedua, email kedua, persetujuan ganda.
- Kepemilikan jadi kabur: tidak jelas siapa yang harus bertindak selanjutnya.
- Support tidak punya visibilitas dan tidak bisa menjawab “di mana macetnya?” tanpa menggali log.
- Logika menunggu (timer, pengingat, tenggat) berakhir sebagai skrip latar belakang rapuh.
Contoh konkret: seorang karyawan meminta akses software. Manajer menyetujui cepat, tapi IT butuh dua hari untuk provisioning. Jika aplikasi tidak bisa menyimpan state proses, mengirim pengingat, dan melanjutkan dengan aman, Anda berujung pada follow-up manual, pengguna bingung, dan kerja ekstra.
Inilah mengapa pilihan antara event-driven workflows vs request-response APIs penting untuk proses bisnis jangka panjang.
Dua model mental: panggilan sinkron vs event dari waktu ke waktu
Perbandingan paling sederhana tergantung pada satu pertanyaan: apakah pekerjaan selesai saat pengguna menunggu, atau terus berjalan setelah mereka pergi?
API request-response adalah pertukaran tunggal: satu panggilan masuk, satu respon keluar. Cocok untuk pekerjaan yang selesai cepat dan dapat diprediksi, seperti membuat record, menghitung kuota, atau mengecek inventaris. Server melakukan pekerjaan, mengembalikan sukses atau gagal, dan interaksi selesai.
Alur kerja berbasis event adalah serangkaian reaksi sepanjang waktu. Sesuatu terjadi (order dibuat, manajer menyetujui, timer kadaluarsa), dan workflow pindah ke langkah berikutnya. Model ini cocok untuk pekerjaan yang melibatkan serah terima, menunggu, retry, dan pengingat.
Perbedaan praktisnya adalah state.
Dengan request-response, state sering tinggal di permintaan saat ini plus memori server sampai respons dikembalikan. Dengan event-driven workflows, state harus disimpan (misalnya di PostgreSQL) supaya proses bisa dilanjutkan nanti.
Penanganan kegagalan juga berubah. Request-response biasanya menangani kegagalan dengan mengembalikan error dan meminta klien mencoba lagi. Workflow mencatat kegagalan dan bisa retry dengan aman saat kondisi membaik. Mereka juga bisa mencatat tiap langkah sebagai event, membuat riwayat lebih mudah direkonstruksi.
Contoh sederhana: “Kirim laporan pengeluaran” bisa sinkron. “Dapat persetujuan, tunggu 3 hari, ingatkan manajer, lalu bayar” bukanlah tugas sinkron.
Persetujuan: bagaimana tiap pendekatan menangani keputusan manusia
Persetujuan adalah area di mana pekerjaan jangka panjang menjadi nyata. Langkah sistem selesai dalam milidetik, tapi manusia bisa menjawab dalam dua menit atau dua hari. Pilihan desain kuncinya adalah apakah Anda memodelkan waktu tunggu itu sebagai proses yang dipause, atau sebagai pesan baru yang datang nanti.
Dengan request-response APIs, persetujuan sering berubah menjadi bentuk yang canggung:
- Blocking (tidak praktis)
- Polling (klien bertanya “sudah disetujui?” berulang kali)
- Callback/webhook (server memanggil Anda kembali nanti)
Semua ini bisa bekerja, tetapi menambah terlalu banyak plumbing hanya untuk menjembatani “waktu manusia” dengan “waktu API.”
Dengan event, persetujuan terbaca seperti sebuah cerita. Aplikasi mencatat sesuatu seperti “ExpenseSubmitted,” lalu nanti menerima “ExpenseApproved” atau “ExpenseRejected.” Mesin workflow (atau state machine Anda sendiri) memindahkan record hanya saat event berikutnya tiba. Ini cocok dengan cara kebanyakan orang berpikir tentang langkah bisnis: kirim, tinjau, putuskan.
Kompleksitas muncul cepat dengan banyak approver dan aturan eskalasi. Anda mungkin memerlukan persetujuan manajer dan finance, tetapi juga mengizinkan manajer senior untuk override. Jika aturan itu tidak dimodelkan dengan jelas, proses menjadi sulit dipahami dan lebih sulit diaudit.
Model persetujuan sederhana yang bisa diskalakan
Polanya adalah menyimpan satu record “request”, lalu menyimpan keputusan secara terpisah. Dengan begitu Anda dapat mendukung banyak approver tanpa menulis ulang logika inti.
Tangkap beberapa data sebagai record kelas pertama:
- Permintaan persetujuan itu sendiri: apa yang disetujui dan status saat ini
- Keputusan individual: siapa yang memutuskan, setuju/tolak, timestamp, alasan
- Approver yang dibutuhkan: peran atau orang, dan aturan urutan jika ada
- Aturan hasil: “salah satu saja”, “mayoritas”, “semua yang diperlukan”, “override diizinkan”
Apa pun implementasinya, selalu simpan siapa yang menyetujui apa, kapan, dan mengapa sebagai data, bukan sekadar baris log.
Timer dan menunggu: pengingat, tenggat, dan eskalasi
Menunggu adalah saat tugas panjang terasa berantakan. Orang makan siang, kalender penuh, dan “kami akan mengabari” berubah jadi “siapa yang pegang ini sekarang?” Ini adalah salah satu perbedaan paling jelas antara event-driven workflows vs request-response APIs.
Dengan request-response APIs, waktu terasa canggung. Panggilan HTTP ada timeout-nya, jadi Anda tidak bisa menjaga permintaan terbuka selama dua hari. Tim biasanya berakhir dengan pola seperti polling, job terjadwal yang memindai database, atau skrip manual ketika sesuatu terlambat. Ini bisa bekerja, tetapi logika menunggu hidup di luar proses. Kasus pinggir mudah terlewat, misalnya apa yang terjadi saat job berjalan dua kali, atau saat record berubah tepat sebelum pengingat dikirim.
Workflow memperlakukan waktu sebagai langkah normal. Anda bisa mengatakan: tunggu 24 jam, kirim pengingat, lalu tunggu sampai total 48 jam dan eskalasi ke approver lain. Sistem menyimpan state, jadi tenggat tidak tersembunyi di proyek “cron + query” terpisah.
Aturan persetujuan sederhana bisa dibaca seperti ini:
Setelah laporan pengeluaran dikirim, tunggu 1 hari. Jika status masih “Pending,” kirim pesan ke manajer. Setelah 2 hari, jika masih pending, alihkan ke lead manajer dan catat eskalasi.
Detail penting adalah apa yang Anda lakukan saat timer menyala tapi keadaan sudah berubah. Workflow yang baik selalu memeriksa ulang state saat ini sebelum bertindak:
- Muat status terbaru
- Pastikan masih pending
- Pastikan assignee masih valid (perubahan tim bisa terjadi)
- Catat apa yang Anda putuskan dan mengapa
Retry dan pemulihan kegagalan tanpa aksi ganda
Retry adalah apa yang Anda lakukan saat sesuatu gagal karena alasan di luar kendali penuh Anda: gateway pembayaran timeout, penyedia email mengembalikan error sementara, atau aplikasi menyimpan langkah A tapi crash sebelum langkah B. Bahayanya sederhana: Anda coba lagi dan tanpa sengaja melakukan tindakan dua kali.
Dengan request-response APIs, pola umum adalah klien memanggil endpoint, menunggu, dan jika tidak mendapat sukses jelas, mencoba lagi. Agar itu aman, server perlu memperlakukan panggilan berulang sebagai intent yang sama.
Perbaikan praktis adalah kunci idempoten: klien mengirim token unik seperti pay:invoice-583:attempt-1. Server menyimpan hasil untuk kunci itu dan mengembalikan hasil yang sama untuk pengulangan. Itu mencegah biaya ganda, tiket duplikat, atau persetujuan ganda.
Event-driven workflows memiliki risiko duplikasi tipe lain. Event sering dikirim setidaknya-sekali (at-least-once), yang berarti duplikat bisa muncul bahkan saat sistem bekerja normal. Konsumen perlu deduplikasi: simpan ID event (atau business key seperti invoice_id + step) dan abaikan pengulangan. Ini adalah perbedaan inti dalam pola orkestrasi workflow: request-response fokus pada replay panggilan dengan aman, sementara event fokus pada replay pesan yang aman.
Beberapa aturan retry yang baik untuk kedua model:
- Gunakan backoff (misalnya 10s, 30s, 2m).
- Tetapkan batas maksimal percobaan.
- Pisahkan error sementara (retry) dari error permanen (gagal cepat).
- Arahkan kegagalan berulang ke status “butuh perhatian”.
- Log setiap percobaan sehingga Anda bisa menjelaskan apa yang terjadi nanti.
Retry harus eksplisit dalam proses, bukan perilaku tersembunyi. Itu membuat kegagalan terlihat dan bisa diperbaiki.
Audit trail: membuat proses bisa dijelaskan
Audit trail adalah file “mengapa” Anda. Saat seseorang bertanya, “Mengapa pengeluaran ini ditolak?” Anda harus bisa menjawab tanpa menebak, bahkan beberapa bulan kemudian. Ini penting baik pada event-driven workflows maupun request-response APIs, tapi bentuknya berbeda.
Untuk proses jangka panjang, catat fakta yang memungkinkan Anda memutar ulang cerita:
- Aktor: siapa yang melakukannya (user, service, atau timer sistem)
- Waktu: kapan itu terjadi (dengan zona waktu)
- Input: apa yang diketahui saat itu (jumlah, vendor, ambang kebijakan, persetujuan)
- Output: keputusan atau aksi yang terjadi (disetujui, ditolak, dibayar, di-retry)
- Versi aturan: versi kebijakan/logic yang dipakai
Event-driven workflows bisa mempermudah audit karena tiap langkah secara alami menghasilkan event seperti “ManagerApproved” atau “PaymentFailed.” Jika Anda menyimpan event tersebut dengan payload dan aktor, Anda mendapatkan timeline yang bersih. Kuncinya adalah membuat event deskriptif dan menyimpannya di tempat yang bisa di-query per kasus.
Request-response APIs masih bisa diaudit, tetapi ceritanya sering tersebar di berbagai layanan. Satu endpoint mencatat “approved,” endpoint lain mencatat “payment requested,” dan yang lain mencatat “retry succeeded.” Jika masing-masing menggunakan format atau field berbeda, audit berubah menjadi pekerjaan detektif.
Perbaikan sederhana adalah shared “case ID” (juga disebut correlation ID). Satu identifier yang Anda lampirkan ke setiap request, event, dan record database untuk instance proses, seperti “EXP-2026-00173.” Kemudian Anda bisa menelusuri seluruh perjalanan lintas langkah.
Memilih pendekatan yang tepat: kekuatan dan trade-off
Pilihan terbaik bergantung pada apakah Anda butuh jawaban segera, atau butuh proses yang terus berjalan selama jam atau hari.
Request-response bekerja baik saat pekerjaan singkat dan aturan sederhana. Pengguna mengirim form, server memvalidasi, menyimpan data, dan mengembalikan sukses atau error. Ini juga cocok untuk aksi satu langkah yang jelas seperti create, update, atau cek izin.
Itu mulai menyakitkan ketika “satu request” diam-diam berubah jadi banyak langkah: menunggu persetujuan, memanggil banyak sistem luar, menangani timeout, atau bercabang berdasarkan hasil berikutnya. Anda harus mempertahankan koneksi (rapuh), atau memindahkan menunggu dan retry ke background job yang sulit dipahami.
Event-driven workflows bersinar ketika proses adalah cerita sepanjang waktu. Tiap langkah bereaksi terhadap event baru (disetujui, ditolak, timer terpicu, pembayaran gagal) dan memutuskan apa yang terjadi selanjutnya. Ini memudahkan pause, resume, retry, dan menjaga jejak yang jelas mengapa sistem melakukan suatu tindakan.
Ada trade-off nyata:
- Sederhana vs tahan banting: request-response lebih mudah mulai, event-driven lebih aman untuk jeda panjang.
- Gaya debugging: request-response mengikuti garis lurus, workflow sering memerlukan penelusuran lintas langkah.
- Tooling dan kebiasaan: event butuh logging yang baik, correlation ID, dan model state yang jelas.
- Manajemen perubahan: workflow berkembang dan bercabang; desain event-driven cenderung menangani jalur baru lebih baik jika dimodelkan dengan baik.
Contoh praktis: laporan pengeluaran yang butuh persetujuan manajer, lalu review finance, lalu pembayaran. Jika pembayaran gagal, Anda mau retry tanpa bayar dua kali. Itu secara alami cocok event-driven. Jika hanya “kirim pengeluaran” dengan cek cepat, request-response sering cukup.
Langkah demi langkah: merancang proses jangka panjang yang tahan jeda
Proses bisnis jangka panjang gagal dengan cara yang membosankan: tab browser tertutup, server restart, persetujuan menunggu tiga hari, atau penyedia pembayaran timeout. Rancang untuk jeda-jeda itu dari awal, terlepas model mana yang Anda pilih.
Mulailah dengan mendefinisikan sejumlah kecil state yang bisa Anda simpan dan lanjutkan. Jika Anda tidak bisa menunjuk state saat ini di database, Anda sebenarnya tidak punya workflow yang bisa dilanjutkan.
Urutan desain sederhana
- Tetapkan batasan: definisikan trigger awal, kondisi akhir, dan beberapa state utama (Pending approval, Approved, Rejected, Expired, Completed).
- Namai event dan keputusan: tuliskan apa yang bisa terjadi sepanjang waktu (Submitted, Approved, Rejected, TimerFired, RetryScheduled). Gunakan nama event bentuk lampau.
- Pilih titik tunggu: identifikasi di mana proses berhenti menunggu manusia, sistem eksternal, atau tenggat waktu.
- Tambahkan aturan timer dan retry per langkah: putuskan apa yang terjadi saat waktu berlalu atau panggilan gagal (backoff, max attempts, eskalasi, menyerah).
- Definisikan bagaimana proses dilanjutkan: pada tiap event atau callback, muat state tersimpan, verifikasi masih valid, lalu pindah ke state berikutnya.
Untuk bertahan dari restart, persistensikan data minimal yang Anda butuhkan untuk melanjutkan dengan aman. Simpan cukup agar bisa menjalankan ulang tanpa menebak:
- ID instance proses dan state saat ini
- Siapa yang bisa bertindak selanjutnya (assignee/role) dan apa yang mereka putuskan
- Tenggat waktu (due_at, remind_at) dan level eskalasi
- Metadata retry (jumlah percobaan, error terakhir, next_retry_at)
- Kunci idempoten atau flag “sudah dilakukan” untuk efek samping (mengirim pesan, menagih kartu)
Jika Anda bisa merekonstruksi “di mana kita” dan “apa yang boleh dilakukan selanjutnya” dari data tersimpan, jeda tidak lagi menakutkan.
Kesalahan umum dan cara menghindarinya
Proses jangka panjang sering rusak hanya setelah pengguna nyata datang. Persetujuan memakan dua hari, retry terpanggil di waktu yang salah, dan Anda berakhir dengan pembayaran ganda atau audit trail yang hilang.
Kesalahan umum:
- Menjaga HTTP request terbuka sambil menunggu persetujuan manusia. Itu timeout, mengikat sumber daya server, dan memberi pengguna kesan palsu bahwa “sedang berlangsung.”
- Retry tanpa idempotensi. Gangguan jaringan berubah menjadi faktur ganda, email ganda, atau transisi “Approved” berulang.
- Tidak menyimpan state proses. Jika state di memori, restart menghapusnya. Jika state hanya di log, Anda tidak bisa melanjutkan dengan andal.
- Membuat audit trail kabur. Event punya jam dan format berbeda, sehingga timeline tidak dapat dipercaya saat insiden atau review kepatuhan.
- Mencampur async dan sync tanpa satu sumber kebenaran. Satu sistem bilang “Paid,” lain bilang “Pending,” dan tidak ada yang tahu yang benar.
Contoh sederhana: laporan pengeluaran disetujui lewat chat, webhook datang terlambat, dan API pembayaran di-retry. Tanpa state tersimpan dan idempotensi, retry bisa mengirim pembayaran dua kali, dan catatan Anda tidak menjelaskan mengapa.
Sebagian besar perbaikan kembali ke eksplisit:
- Persistensi transisi state (Requested, Approved, Rejected, Paid) di database, dengan siapa/apa yang mengubahnya.
- Gunakan kunci idempoten untuk setiap efek samping eksternal (pembayaran, email, tiket) dan simpan hasilnya.
- Pisahkan “menerima permintaan” dari “menyelesaikan pekerjaan”: kembalikan respons cepat, lalu selesaikan workflow di latar belakang.
- Standarkan timestamp (UTC), tambahkan correlation ID, dan catat baik permintaan maupun hasilnya.
Daftar periksa cepat sebelum membangun
Pekerjaan jangka panjang lebih tentang tetap benar setelah jeda, manusia, dan kegagalan, daripada satu panggilan sempurna.
Tuliskan apa arti “aman untuk melanjutkan” untuk proses Anda. Jika aplikasi restart di tengah jalan, Anda harus bisa melanjutkan dari langkah terakhir yang dikenal tanpa menebak.
Daftar periksa praktis:
- Definisikan bagaimana proses dilanjutkan setelah crash atau deploy. State apa yang disimpan, dan apa yang berjalan selanjutnya?
- Beri setiap instance kunci proses unik (mis. ExpenseRequest-10482) dan model status yang jelas (Submitted, Waiting for Manager, Approved, Paid, Failed).
- Perlakukan persetujuan sebagai record, bukan hanya outcome: siapa menyetujui atau menolak, kapan, dan alasan atau komentar.
- Peta aturan menunggu: pengingat, tenggat, eskalasi, kadaluarsa. Tetapkan pemilik untuk tiap timer (manajer, finance, sistem).
- Rencanakan penanganan kegagalan: retry harus terbatas dan aman, dan harus ada titik “butuh review” di mana manusia dapat memperbaiki data atau menyetujui percobaan ulang.
Tes kewarasan: bayangkan penyedia pembayaran timeout setelah Anda sudah menagih kartu. Desain Anda harus mencegah penagihan dua kali, sekaligus membiarkan proses selesai.
Contoh: persetujuan pengeluaran dengan tenggat dan retry pembayaran
Skenario: seorang karyawan mengirimkan nota taksi $120 untuk reimbursement. Perlu persetujuan manajer dalam 48 jam. Jika disetujui, sistem membayar. Jika pembayaran gagal, sistem melakukan retry dengan aman dan meninggalkan catatan yang jelas.
Walkthrough request-response
Dengan request-response APIs, aplikasi sering berperilaku seperti percakapan yang harus terus dicek.
Karyawan menekan Submit. Server membuat record reimbursement dengan status “Pending approval” dan mengembalikan ID. Manajer mendapat notifikasi, tapi aplikasi karyawan biasanya harus polling untuk melihat apakah ada perubahan, misalnya: “GET reimbursement status by ID.”
Untuk menegakkan tenggat 48 jam, Anda harus menjalankan job terjadwal yang memindai request yang overdue, atau menyimpan timestamp deadline dan memeriksanya selama polling. Jika job terlambat, pengguna bisa melihat status usang.
Saat manajer menyetujui, server mengganti status menjadi “Approved” dan memanggil penyedia pembayaran. Jika Stripe mengembalikan error sementara, server harus memutuskan retry sekarang, retry nanti, atau gagal. Tanpa kunci idempoten yang hati-hati, retry bisa membuat payout ganda.
Walkthrough event-driven
Di model event-driven, setiap perubahan adalah fakta yang dicatat.
Karyawan submit, menghasilkan event “ExpenseSubmitted.” Sebuah workflow dimulai dan menunggu baik “ManagerApproved” atau event timer “DeadlineReached” pada 48 jam. Jika timer yang lebih dulu terjadi, workflow mencatat hasil “AutoRejected” dan alasannya.
Saat disetujui, workflow mencatat “PayoutRequested” dan mencoba pembayaran. Jika Stripe timeout, workflow mencatat “PayoutFailed” dengan kode error, menjadwalkan retry (mis. 15 menit), dan hanya mencatat “PayoutSucceeded” sekali menggunakan kunci idempoten.
Apa yang dilihat pengguna tetap sederhana:
- Pending approval (48 jam tersisa)
- Disetujui, sedang dibayarkan
- Retry pembayaran dijadwalkan
- Dibayar
Audit trail terbaca seperti timeline: submitted, approved, deadline diperiksa, payout dicoba, gagal, di-retry, dibayar.
Langkah selanjutnya: mengubah model menjadi aplikasi kerja
Pilih satu proses nyata dan bangun end to end sebelum Anda menggeneralisasi. Persetujuan pengeluaran, onboarding, dan penanganan refund adalah starter yang baik karena melibatkan langkah manusia, menunggu, dan jalur kegagalan. Tetapkan tujuan kecil: satu happy path dan dua pengecualian paling umum.
Tulis proses sebagai state dan event, bukan sebagai tampilan layar. Contoh: “Submitted” -> “ManagerApproved” -> “PaymentRequested” -> “Paid,” dengan cabang seperti “ApprovalRejected” atau “PaymentFailed.” Saat Anda melihat titik tunggu dan efek samping dengan jelas, pilihan antara event-driven workflows vs request-response APIs menjadi praktis.
Putuskan di mana state proses disimpan. Database bisa cukup jika alurnya sederhana dan Anda bisa menegakkan update di satu tempat. Workflow engine membantu saat Anda butuh timer, retry, dan branching, karena ia melacak apa yang harus dilakukan selanjutnya.
Tambahkan field audit sejak hari pertama. Simpan siapa melakukan apa, kapan, dan mengapa (komentar atau kode alasan). Saat seseorang bertanya, “Mengapa pembayaran ini di-retry?” Anda ingin jawaban yang jelas tanpa menggali log.
Jika Anda membangun jenis workflow ini di platform no-code, AppMaster (appmaster.io) adalah salah satu opsi di mana Anda bisa memodelkan data di PostgreSQL dan membangun logika proses secara visual, yang bisa membuat persetujuan dan audit trail lebih mudah konsisten di web dan mobile.
FAQ
Gunakan request-response saat pekerjaan selesai dengan cepat dan dapat diprediksi saat pengguna menunggu, seperti membuat record atau memvalidasi form. Gunakan event-driven workflow ketika proses berlangsung menit hingga hari, melibatkan persetujuan manusia, atau membutuhkan timer, retry, dan kemampuan melanjutkan dengan aman setelah restart.
Tugas jangka panjang tidak cocok dijalankan sebagai satu HTTP request karena koneksi bisa time out, server bisa restart, dan pekerjaan sering bergantung pada orang atau sistem eksternal. Jika Anda memperlakukannya sebagai satu panggilan, biasanya state hilang, retry menimbulkan duplikat, dan logika menunggu tersebar di skrip latar belakang.
Persistenkan state proses yang jelas di database Anda dan majukan state hanya melalui transisi eksplisit. Simpan ID instance proses, status saat ini, siapa yang boleh bertindak selanjutnya, dan timestamp penting agar dapat melanjutkan dengan aman setelah deploy, crash, atau jeda.
Modelkan persetujuan sebagai langkah yang dipause dan dilanjutkan ketika keputusan tiba, bukan men-block atau polling terus-menerus. Catat setiap keputusan sebagai data (siapa yang memutuskan, kapan, setuju/tolak, dan alasannya) sehingga workflow dapat maju secara prediktabel dan dapat diaudit nanti.
Polling bisa bekerja untuk kasus sederhana, tapi menambah beban karena klien harus terus bertanya “sudah selesai?” Default yang lebih baik adalah mendorong notifikasi saat terjadi perubahan dan biarkan klien memperbarui tampilan saat perlu, sementara server tetap menjadi sumber kebenaran untuk state.
Anggap waktu sebagai bagian proses: simpan deadline dan waktu pengingat, lalu saat timer terpanggil selalu periksa state terbaru sebelum bertindak. Ini menghindari mengirim pengingat setelah sesuatu sudah disetujui dan menjaga konsistensi eskalasi meskipun job berjalan terlambat atau dipanggil dua kali.
Mulailah dengan kunci idempoten untuk setiap efek samping seperti menagih kartu atau mengirim email, dan simpan hasilnya untuk kunci itu. Dengan begitu retry jadi aman karena mengulangi intent yang sama mengembalikan hasil yang sama alih-alih melakukan aksi dua kali.
Asumsikan pesan bisa dikirim lebih dari sekali dan desain konsumer untuk deduplikasi. Pendekatan praktis adalah simpan ID event (atau business key untuk langkah itu) dan abaikan pengulangan sehingga replay tidak memicu aksi yang sama dua kali.
Tangkap timeline fakta: aktor, timestamp, input pada saat itu, outcome, dan versi aturan atau kebijakan yang digunakan. Beri juga satu case ID atau correlation ID pada semua yang terkait proses agar tim support bisa menjawab “di mana macetnya?” tanpa menelusuri log yang tidak relevan.
Simpan satu record request sebagai “case”, simpan keputusan secara terpisah, dan majukan state melalui transisi yang dipersist sehingga bisa di-replay. Di platform no-code seperti AppMaster (appmaster.io) Anda bisa memodelkan data di PostgreSQL dan mengimplementasikan logika langkah secara visual, yang membantu menjaga konsistensi persetujuan, retry, dan field audit di seluruh aplikasi.


