Propagasi Deadline Menjaga Budget Waktu Request
Sebuah request dapat melewati beberapa service sebelum menghasilkan response. Setiap hop mungkin memiliki queue, network call, retry policy, dan timeout lokal sendiri. Jika batas tersebut ditentukan secara independen, total request path dapat berjalan jauh lebih lama daripada waktu yang bersedia ditunggu caller.
Propagasi deadline memberi seluruh path satu boundary waktu. Caller awal mengirim absolute deadline, atau time budget yang dikonversi menjadi deadline. Setiap komponen downstream memakai interval yang tersisa alih-alih memulai timeout baru dari nol.
budget caller: 800 ms
API menerima pada +40 ms -> tersisa sekitar 760 ms
service menerima pada +170 ms -> tersisa sekitar 630 ms
database mulai pada +310 ms -> tersisa sekitar 490 msTujuannya bukan membuat pekerjaan lebih cepat. Mekanisme ini menghentikan pekerjaan ketika hasilnya tidak lagi dapat tiba dalam masa guna request.
Timeout independen dapat melampaui batas end-to-end
Misalkan API memberi 500 ms kepada service downstream, lalu service tersebut secara independen memberi 500 ms kepada database call. Request yang sudah menghabiskan 300 ms di queue dan network transit masih dapat memulai operasi setengah detik lagi.
300 ms sudah terpakai
+ 500 ms timeout downstream
= 800 ms kemungkinan elapsed timeCaller dengan batas 600 ms mungkin sudah terputus sebelum backend selesai. Backend tetap memakai connection, worker slot, CPU time, atau kapasitas database untuk hasil yang tidak dapat dipakai siapa pun.
Timeout lokal tetap berguna sebagai safety bound yang lebih ketat. Batas lokal hanya tidak seharusnya melewati sisa end-to-end deadline.
effective timeout = min(local limit, remaining request budget)Absolute deadline mencegah budget dimulai ulang
Mengirim timeout=500ms pada setiap hop bersifat ambigu karena setiap receiver dapat menafsirkannya sebagai interval 500 ms yang baru. Absolute deadline menunjuk satu titik akhir waktu.
deadline = 2026-09-21T09:00:00.800ZSetiap service membandingkan deadline tersebut dengan clock saat ini dan menghitung sisa budget. Dengan begitu, waktu yang sudah terpakai dalam transit dan queue tetap masuk ke boundary accounting yang sama.
Absolute deadline bergantung pada clock antar-machine yang cukup selaras. Sistem dengan sinkronisasi clock lemah dapat meneruskan remaining duration sambil mengurangi elapsed time lokal pada setiap boundary. Pendekatan ini menghindari perbandingan wall clock langsung, tetapi perlu penanganan cermat agar serialization dan transit tidak tanpa sengaja mengembalikan budget.
Queue time termasuk bagian dari budget
Kesalahan yang umum adalah memulai operation timeout hanya setelah worker mulai mengeksekusi pekerjaan. Saat load tinggi, request dapat menghabiskan sebagian besar masa gunanya dengan menunggu di queue sebelum timer tersebut dimulai.
Admission yang sadar deadline memeriksa request sebelum pekerjaan mahal dimulai:
if now >= deadline:
reject or cancel
else:
start work with remaining budgetPolicy yang lebih selektif dapat menolak pekerjaan lebih awal ketika sisa budget berada di bawah minimum execution window yang masih berguna. Jika operasi database biasanya memerlukan puluhan milidetik, memulainya dengan sisa satu milidetik umumnya hanya menambah load tanpa jalur keberhasilan yang realistis.
Threshold sebaiknya berasal dari perilaku service dan semantic produk, bukan konstanta arbitrer yang disalin ke semua endpoint.
Cancellation perlu mengikuti expiry deadline
Deadline hanya memberi sedikit nilai operasional jika expiry sekadar mengubah response kepada caller sementara pekerjaan downstream terus berjalan tanpa perubahan.
Ketika budget habis, cancellation perlu diteruskan ke operasi yang mendukungnya: RPC, database query, stream read, worker task, dan unit lain yang dapat dibatalkan. Resource cleanup tetap harus berjalan agar connection, permit, lock, dan buffer dilepas.
deadline habis
|
+--> cancel RPC
+--> cancel query
+--> release permit
+--> stop response workCancellation bersifat cooperative pada banyak runtime. Kode yang menjalankan CPU loop panjang atau memanggil API tanpa dukungan cancellation dapat terus berjalan sampai mencapai cancellation point. Meneruskan signal karena itu perlu, tetapi komponen mahal juga harus menghormatinya.
Retry memakai budget yang sama
Retry adalah attempt lain di dalam masa hidup request awal, bukan masa hidup request baru. Retry policy perlu memperhitungkan elapsed time, backoff, dan perkiraan biaya attempt berikutnya.
remaining = 180 ms
backoff = 80 ms
attempt budget needed = 150 msPada kondisi tersebut, menunggu backoff lalu menjalankan attempt tidak dapat masuk ke sisa 180 ms. Tetap memulainya meningkatkan traffic downstream tanpa mempertahankan jalur completion yang masuk akal.
Retry logic dapat mensyaratkan minimum remaining budget sebelum menjadwalkan attempt berikutnya. Ini juga membatasi retry amplification mendekati deadline expiry, ketika banyak caller dapat memulai pekerjaan yang hampir pasti segera dibatalkan.
Fan-out memerlukan boundary waktu bersama
Aggregator dapat memanggil beberapa dependency secara paralel. Setiap branch mewarisi parent deadline, sedangkan branch individual dapat memakai local limit yang lebih ketat.
parent deadline T
|-- inventory: min(T, local inventory limit)
|-- pricing: min(T, local pricing limit)
+-- profile: min(T, local profile limit)Satu branch lambat tidak boleh diam-diam memperpanjang parent request. Aggregator juga memerlukan policy eksplisit untuk partial result: menggagalkan seluruh operasi, menghilangkan branch opsional, mengembalikan stale data, atau memakai fallback lain yang sudah ditetapkan.
Deadline menyediakan boundary waktu; deadline tidak menentukan semantic fallback pada level produk.
Background work memerlukan lifetime terpisah
Sebagian pekerjaan tetap bernilai setelah request awal berakhir. Audit delivery, asynchronous indexing, atau durable job submission dapat memang dirancang untuk berjalan lebih lama daripada HTTP response.
Pekerjaan semacam itu perlu melewati ownership boundary yang eksplisit. Setelah diterima oleh durable queue atau sistem background lain, pekerjaan mendapat deadline, retry policy, dan cancellation semantic sendiri. Menggunakan context caller tanpa pemisahan dapat membatalkan background work yang sah segera setelah response selesai.
Risiko sebaliknya juga ada: melepaskan pekerjaan request biasa dari caller hanya untuk menghindari cancellation dapat meninggalkan banyak orphaned work yang tetap berjalan setelah client pergi.
Telemetry perlu mengekspos sisa budget
Latency metric menunjukkan berapa lama operasi berlangsung, sedangkan deadline telemetry menunjukkan seberapa dekat operasi tersebut dengan titik ketika hasilnya tidak lagi berguna.
Signal yang berguna mencakup remaining budget saat service entry, queue delay, operasi yang dilewati karena budget tidak cukup, cancellation akibat deadline expiry, retry attempt yang ditekan, serta downstream call yang masih berjalan setelah parent cancellation.
request_budget_ms=800
entry_remaining_ms=612
queue_delay_ms=94
db_start_remaining_ms=301
retry_suppressed=trueDistributed trace dapat merekam parent deadline atau remaining budget pada span utama. Trace kemudian dapat memperlihatkan service yang berulang kali menerima request dengan sisa waktu hampir habis, yang mengarah pada queueing upstream atau target end-to-end yang tidak realistis.
Propagasi deadline mengubah timeout handling dari kumpulan timer yang tidak terkait menjadi accounting resource end-to-end. Satu request budget yang terus berkurang sepanjang sistem memberi service dasar yang konsisten untuk admission, retry, cancellation, dan cleanup, sambil tetap memungkinkan local limit yang lebih ketat ketika dependency membutuhkannya.