Webhook6 Agustus 20267 mnt baca

Twilio Memberi Kenop Timeout. Hampir Tidak Ada yang Memutarnya.

Twilio satu-satunya pengirim besar dengan lima kenop: connect timeout, read timeout, total waktu, jumlah dan kebijakan retry. Tidak ada yang memutarnya.

TWILIO MEMBOLEHKAN ANDA MENGATUR INI. HAMPIR TIDAK ADA YANG MELAKUKANNYA.ct · koneksidefault 5000ms · maks. 10000ms · koneksi TCPrt · bacadefault 15000ms · maks. 15000ms · byte pertamatt · totaldefault 15000ms · maks. 15000ms · semua percobaanrc = jumlah percobaan ulang, 0 sampai 5, default 1 · rp = kegagalan mana yang layak dicoba ulang
Connect, read, dan total, masing-masing dengan nilai default dan batas atas. Semua yang melewati batas atas tidak bisa ditawar.

Setiap pengirim webhook lain memberi Anda satu angka dan berharap Anda menerimanya begitu saja. Lima detik milik Shopify, sepuluh milik GitHub, tiga milik Slack, semuanya kami kumpulkan di referensi provider webhook kami. Anda boleh mengeluhkannya, tetapi Anda tidak bisa mengubahnya.

Twilio adalah pengecualian. Twilio membuka timeout sebagai parameter pada webhook itu sendiri, bersama jumlah percobaan ulang (retry) dan kebijakan tentang kegagalan mana yang layak dicoba ulang. Lima kenop, semuanya dikirim dengan nilai default, dan di sebagian besar integrasi tidak ada yang pernah menyentuhnya.

Itu kesempatan yang terlewat di kedua arah, karena nilai default-nya salah untuk dua kasus yang paling umum.

TL;DR

  • ct connect timeout: default 5000ms, rentang 100 sampai 10000
  • rt read timeout: default 15000ms, rentang 100 sampai 15000
  • tt total waktu termasuk percobaan ulang: default 15000ms, rentang 100 sampai 15000
  • rc jumlah percobaan ulang: 0 sampai 5, default 1
  • rp kebijakan percobaan ulang: jenis kegagalan mana yang layak dicoba ulang
  • Batas atasnya mutlak. Anda tidak bisa membeli read timeout lebih dari 15 detik berapa pun harganya

Tiga timeout, bukan satu

Kebanyakan orang hanya punya satu gambaran tentang timeout webhook: berapa lama pengirim menunggu respons. Twilio membaginya menjadi tiga tahap, dan mengetahui tahap mana yang Anda langgar mengubah diagnosisnya sepenuhnya.

ct adalah “waktu dalam milidetik yang ditunggu Twilio untuk membuka koneksi TCP ke server Anda.” Default 5000ms, maksimum 10000ms. Jika batas ini terlampaui, artinya Twilio sama sekali tidak bisa membuka socket. Penyebabnya DNS, TLS, firewall, atau origin yang mati total. Ini tidak pernah berarti handler Anda lambat, karena handler Anda belum berjalan.

rt adalah “waktu dalam milidetik yang ditunggu Twilio untuk setiap paket respons HTTP setelah mengirim permintaan webhook.” Default 15000ms, maksimum 15000ms. Inilah yang dimaksud orang saat menyebut timeout, dan inilah batas waktu yang sebenarnya untuk handler Anda.

tt adalah “total waktu yang diizinkan untuk semua timeout, termasuk percobaan ulang.” Default 15000ms, maksimum 15000ms. Ini adalah batas atas untuk seluruh rangkaian upaya, dan parameter inilah yang sering menjebak orang, karena ia juga membatasi percobaan ulang.

TWILIO MEMBOLEHKAN ANDA MENGATUR INI. HAMPIR TIDAK ADA YANG MELAKUKANNYA.ct · koneksidefault 5000ms · maks. 10000ms · koneksi TCPrt · bacadefault 15000ms · maks. 15000ms · byte pertamatt · totaldefault 15000ms · maks. 15000ms · semua percobaanrc = jumlah percobaan ulang, 0 sampai 5, default 1 · rp = kegagalan mana yang layak dicoba ulang

Perhatikan bahwa tt dan rt punya default yang sama dan maksimum yang sama. Dengan default bawaan, satu read timeout menghabiskan seluruh jatah total waktu, dan percobaan ulang yang Anda kira sudah dikonfigurasi tidak pernah sempat berjalan. Jika Anda ingin percobaan ulang ada gunanya, Anda harus menurunkan rt agar dua upaya atau lebih muat di dalam tt.

Interaksi itu adalah hal paling berguna untuk dipahami di sini, dan tidak terlihat jelas jika Anda membaca parameternya satu per satu.

Mengaturnya agar percobaan ulang benar-benar terjadi

Misalkan handler Anda biasanya menjawab dalam 400ms dan Anda menginginkan dua percobaan ulang sebelum menyerah.

rt = 3000     // 3s per attempt, generous against a 400ms handler
rc = 2        // two retries
tt = 12000    // room for three attempts plus connect overhead
ct = 3000     // fail fast if the socket will not open
rp = ct,rt,5xx

Sekarang handler yang macet ditinggalkan setelah tiga detik, bukan lima belas, dan percobaan ulang tiba selagi insidennya masih insiden yang sama. Bandingkan dengan default, ketika satu permintaan yang macet menghabiskan seluruh lima belas detik itu dan percobaan ulang yang sudah dikonfigurasi diam-diam tidak pernah terjadi.

Kebijakan percobaan ulang layak diatur dengan sengaja. Mencoba ulang 4xx biasanya salah, karena 400 atau 404 berarti permintaannya sendiri tidak dapat diterima dan mengirimnya lagi akan menghasilkan jawaban yang sama. Coba ulang connect timeout, read timeout, dan 5xx, yaitu kegagalan yang mungkin bersifat sementara. Ini penalaran yang sama dengan Backoff Eksponensial dan Jitter untuk Percobaan Ulang Webhook, diterapkan pada pengirim yang memungkinkan Anda menuangkannya dalam konfigurasi.

URL fallback adalah separuh lainnya

Dokumentasi Twilio menyarankan timeout yang lebih pendek “untuk mempercepat failover ke URL fallback jika terjadi gangguan di server Anda.”

URL fallback adalah endpoint kedua yang dipanggil Twilio saat endpoint utama gagal, dan ini hal paling mirip circuit breaker bawaan yang ditawarkan pengirim besar mana pun. URL ini hanya membantu jika timeout-nya cukup pendek untuk sampai ke sana selagi penelepon masih tersambung, dan justru karena itulah rt dan ct penting untuk suara dan pesan, tidak seperti pada webhook pembayaran.

Arahkan ke sesuatu yang tidak bisa gagal karena alasan yang sama dengan endpoint utama. Fallback di host yang sama, di balik load balancer yang sama, dengan database yang sama, bukanlah fallback. TwiML statis yang disajikan dari object store, itulah fallback.

Kasus yang tidak bisa diatasi dengan kenop

Ada satu kategori yang tidak bisa diselamatkan konfigurasi Twilio, dan kategori ini makin lama makin umum.

SMS masuk tiba, dan Anda ingin LLM menulis balasannya. Panggilan itu butuh dua puluh sampai enam puluh detik. Batas atas read timeout adalah lima belas, dan Anda tidak bisa menaikkannya. Tidak ada kombinasi rt, tt, dan rc yang membuat handler enam puluh detik muat dalam maksimum lima belas detik.

Jawabannya sama seperti untuk Slack: konfirmasi dan balas secara terpisah. Kembalikan TwiML kosong segera agar jam Twilio berhenti, lalu kirim balasan sebenarnya lewat Messages API saat model selesai.

export async function POST(req: Request) {
  const raw = await req.text();                     // raw body, for the signature
  if (!verifyTwilioSignature(req.url, raw, req.headers.get("x-twilio-signature"))) {
    return new Response("unauthorized", { status: 403 });
  }

  await queue.publish(raw);                         // durable, ~10ms

  // Empty TwiML: acknowledged, nothing to say yet
  return new Response('<?xml version="1.0" encoding="UTF-8"?><Response></Response>', {
    headers: { "content-type": "text/xml" },
  });
}

Worker kemudian memanggil messages.create saat jawabannya sudah ada. Pengguna melihat balasan tiba dalam satu menit, hal yang wajar untuk percakapan teks. Twilio melihat respons dalam 40 milidetik. Versi yang lebih luas dari argumen ini ada di Webhook untuk Agen AI.

Untuk panggilan suara, padanannya adalah mengembalikan TwiML yang memutar pesan atau memasukkan penelepon ke antrean selagi pekerjaan sebenarnya berjalan, karena penelepon yang hanya mendengar keheningan adalah kegagalan yang lebih buruk daripada SMS yang lambat.

Verifikasi tanda tangan (signature) berbeda di sini

X-Twilio-Signature bukan HMAC biasa atas body. Twilio menyusun string yang ditandatangani dari URL permintaan lengkap, ditambah, untuk permintaan form-encoded, parameter POST yang diurutkan berdasarkan key lalu digabungkan. Kemudian HMAC-SHA1 dengan auth token Anda, lalu dikodekan ke base64.

Dua konsekuensi praktis.

URL adalah bagian dari tanda tangan, jadi apa pun yang menulis ulang URL akan merusak verifikasi. Proxy yang membuang port, load balancer yang mengubah skema dari https ke http, atau framework yang menyusun ulang URL dari header, semuanya akan menghasilkan permintaan yang tampak valid tetapi gagal diperiksa. Jika verifikasi gagal di production dan lolos di lokal, bandingkan URL persis yang ditandatangani kode Anda dengan URL yang dipanggil Twilio.

Algoritmenya SHA1, bukan SHA256, dan untuk permintaan form-encoded, input-nya bukan raw body. Gunakan helper validateRequest milik Twilio sendiri alih-alih mengadaptasi verifier ala Stripe, karena konstruksinya memang berbeda. Perbandingan antar-provider ada di Verifikasi Tanda Tangan Webhook Stripe, GitHub, dan Shopify.

Peran AnyHook

Kenop ini berguna, dan batas atasnya mutlak. Lima belas detik adalah waktu terlama yang akan ditunggu Twilio, dan banyak handler yang sah butuh lebih dari itu, terutama panggilan LLM. Pemeriksa timeout mengukur waktu handler Anda terhadap lima belas detik itu, dan Handler Webhook Anda Memanggil LLM berisi solusi jawab-dulu untuk setiap platform.

Arahkan webhook ke in.anyhook.net/you/twilio, dan batas atas itu tidak lagi menjadi batas atas Anda. AnyHook menjawab dari edge (Cloudflare Worker AnyHook di in.anyhook.net) dalam sekitar satu detik, lalu mengirim ke handler Anda dengan batas waktu pengiriman 60 sampai 300 detik, tergantung paket dan dalam batas jatah komputasi (compute allowance) paket tersebut.

  • Percobaan ulang ke endpoint Anda berjalan dengan backoff eksponensial dan jauh lebih lama daripada yang diizinkan tt
  • Setiap event disimpan secara persisten sebelum pengiriman, jadi handler yang gagal cukup diatasi dengan putar ulang (replay), bukan menjadi pesan yang hilang
  • Peringatan kegagalan pada 1, 5, dan 20 kegagalan berturut-turut, dengan jeda otomatis pada 20

Jika Anda butuh TwiML di dalam respons, tangani itu di handler Anda sendiri. Relay adalah bentuk yang tepat ketika webhook-nya berupa notifikasi, bukan permintaan instruksi.

Kesimpulan

Twilio memberi Anda kendali atas waktu webhook yang lebih besar daripada pengirim besar lainnya, dan nilai default-nya diatur untuk handler yang menjawab seketika. Turunkan rt agar percobaan ulang muat di dalam tt, atur rp agar melewati 4xx, dan arahkan URL fallback ke sesuatu dengan mode kegagalan yang berbeda.

Lalu terima batas atas itu apa adanya. Lima belas detik adalah maksimumnya, dan jika handler Anda butuh satu menit, tidak ada konfigurasi yang bisa membawa Anda ke sana. Konfirmasi dulu, lalu balas lewat jalur terpisah.

Semua artikel6 Agustus 2026 · 7 mnt

Berhenti kehilangan webhook.

Ganti satu URL. Dapatkan percobaan ulang, log event, dan putar ulang sekali klik. Atau lihat dulu: daftar dan jalankan latihan gangguan 30 detik, lalu saksikan event tetap selamat saat server Anda mati. Tidak perlu server.