KoderKoder.ai
HargaEnterpriseEdukasiUntuk investor
MasukMulai

Produk

HargaEnterpriseUntuk investor

Sumber daya

Hubungi kamiDukunganEdukasiBlog

Legal

Kebijakan privasiKetentuan penggunaanKeamananKebijakan penggunaan yang dapat diterimaLaporkan penyalahgunaan

Sosial

LinkedInTwitter
Koder.ai
Bahasa

© 2026 Koder.ai. Hak cipta dilindungi.

Beranda›Blog›Timeout context di Go: resep praktis untuk API yang cepat
04 Jan 2026·6 menit

Timeout context di Go: resep praktis untuk API yang cepat

Timeout context Go mencegah panggilan DB lambat dan permintaan eksternal menumpuk. Pelajari propagasi batas waktu, pembatalan, dan default yang aman.

Timeout context di Go: resep praktis untuk API yang cepat

Mengapa permintaan lambat bisa melemahkan API

Satu permintaan yang lambat jarang "hanya lambat." Saat menunggu, permintaan itu menjaga goroutine tetap hidup, memakan memori untuk buffer dan objek respons, dan sering menempati koneksi database atau slot di pool. Ketika cukup banyak permintaan lambat menumpuk, API Anda berhenti melakukan pekerjaan berguna karena sumber daya terbatasnya terikat menunggu.

Anda biasanya merasakannya di tiga tempat. Goroutine menumpuk dan overhead penjadwalan naik, sehingga latensi memburuk untuk semua orang. Pool database kehabisan koneksi bebas, sehingga query cepat pun mulai antre di belakang yang lambat. Memori naik dari data dalam perjalanan dan respons yang baru dibangun sebagian, yang meningkatkan kerja GC.

Menambah lebih banyak server sering kali tidak memperbaiki masalah. Jika setiap instance terkena bottleneck yang sama (pool DB kecil, upstream lambat, batas rate bersama), Anda hanya memindahkan antrean dan membayar lebih sementara error tetap melompat.

Bayangkan sebuah handler yang melakukan fan-out: memuat user dari PostgreSQL, memanggil layanan pembayaran, lalu memanggil layanan rekomendasi. Jika panggilan rekomendasi macet dan tidak ada yang membatalkannya, permintaan tidak pernah selesai. Koneksi DB mungkin dikembalikan, tetapi goroutine dan sumber daya client HTTP tetap terikat. Kalikan itu dengan ratusan permintaan dan Anda mendapatkan meltdown lambat.

Tujuannya sederhana: tetapkan batas waktu yang jelas, hentikan pekerjaan saat waktunya habis, bebaskan sumber daya, dan kembalikan error yang dapat diprediksi. Timeout context di Go memberi setiap langkah sebuah deadline sehingga pekerjaan berhenti saat pengguna tidak lagi menunggu.

Timeout context dalam istilah sederhana

Sebuah context.Context adalah objek kecil yang Anda teruskan ke bawah rantai panggilan sehingga setiap lapisan sepakat pada satu hal: kapan permintaan ini harus dihentikan. Timeout adalah cara umum untuk mencegah satu dependensi yang lambat mengikat server Anda.

Sebuah context dapat membawa tiga jenis informasi: sebuah deadline (kapan pekerjaan harus berhenti), sinyal pembatalan (seseorang memutuskan berhenti lebih awal), dan beberapa nilai yang scoped ke request (gunakan ini hemat-hati, dan jangan untuk data besar).

Pembatalan bukan sihir. Sebuah context mengekspos channel Done(). Ketika channel itu ditutup, permintaan dibatalkan atau waktunya habis. Kode yang menghormati context memeriksa Done() (sering dengan select) dan mengembalikan lebih awal. Anda juga bisa memeriksa ctx.Err() untuk mengetahui mengapa context berakhir, biasanya context.Canceled atau context.DeadlineExceeded.

Gunakan context.WithTimeout untuk "berhenti setelah X detik." Gunakan context.WithDeadline ketika Anda sudah tahu waktu cutoff yang tepat. Gunakan context.WithCancel ketika kondisi induk harus menghentikan pekerjaan (klien terputus, pengguna pindah halaman, Anda sudah punya jawaban).

Saat sebuah context dibatalkan, perilaku yang benar itu membosankan tapi penting: hentikan pekerjaan, berhenti menunggu I/O lambat, dan kembalikan error yang jelas. Jika sebuah handler menunggu query database dan context berakhir, kembalikan cepat dan biarkan panggilan database berhenti jika mendukung context.

Tetapkan batas waktu di boundary API

Tempat paling aman untuk menghentikan permintaan lambat adalah boundary tempat trafik masuk ke layanan Anda. Jika sebuah permintaan akan timeout, Anda ingin itu terjadi secara prediktabel dan sejak awal, bukan setelah mengikat goroutine, koneksi DB, dan memori.

Mulai di edge (load balancer, API gateway, reverse proxy) dan tetapkan batas keras berapa lama sebuah request diizinkan hidup. Itu melindungi service Go Anda bahkan jika seorang handler lupa menetapkan timeout.

Di dalam server Go Anda, atur timeout HTTP sehingga server tidak menunggu selamanya untuk klien yang lambat atau respons yang macet. Sebagai minimum, konfigurasikan timeout untuk membaca header, membaca body penuh request, menulis respons, dan menjaga koneksi idle tetap hidup.

Pilih anggaran request default yang sesuai produk Anda. Untuk banyak API, 1 sampai 3 detik adalah titik awal yang masuk akal untuk permintaan tipikal, dengan batas lebih tinggi untuk operasi yang diketahui lambat seperti ekspor. Angka pastinya kurang penting dibanding konsistensi, pengukuran, dan aturan yang jelas untuk pengecualian.

Respons streaming butuh perhatian ekstra. Mudah membuat stream tak berujung secara tidak sengaja di mana server mempertahankan koneksi terbuka dan menulis potongan kecil terus-menerus, atau menunggu selamanya sebelum byte pertama. Putuskan di awal apakah endpoint benar-benar stream. Jika tidak, terapkan waktu total maksimum dan waktu maksimum-ke-byte-pertama.

Setelah boundary punya deadline yang jelas, jauh lebih mudah untuk mempropagasikan deadline itu ke seluruh permintaan.

Langkah demi langkah: tambahkan timeout ke handler HTTP

Tempat paling sederhana untuk memulai adalah handler HTTP. Di sinilah satu request masuk ke sistem Anda, jadi ini lokasi alami untuk menetapkan batas keras.

1) Turunkan context yang ber-waktu

Buat context baru dengan deadline, dan pastikan Anda memanggil cancel. Lalu teruskan context itu ke segala hal yang mungkin block: pekerjaan database, panggilan HTTP, atau komputasi lambat.

func (s *Server) GetUser(w http.ResponseWriter, r *http.Request) {
	ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
	defer cancel()

	userID := r.URL.Query().Get("id")
	if userID == "" {
		http.Error(w, "missing id", http.StatusBadRequest)
		return
	}

	user, err := s.loadUser(ctx, userID)
	if err != nil {
		writeError(w, ctx, err)
		return
	}

	writeJSON(w, http.StatusOK, user)
}

2) Teruskan ctx ke setiap panggilan blocking

Aturan yang baik: jika sebuah fungsi bisa menunggu I/O, ia harus menerima context.Context. Jaga handler agar tetap terbaca dengan mendorong detail ke helper kecil seperti loadUser.

func (s *Server) loadUser(ctx context.Context, id string) (User, error) {
	return s.repo.GetUser(ctx, id) // repo should use QueryRowContext/ExecContext
}

3) Kembalikan lebih awal saat context selesai

Jika deadline tercapai (atau klien terputus), hentikan pekerjaan dan kembalikan respons yang ramah pengguna. Pemetaan umum adalah context.DeadlineExceeded ke 504 Gateway Timeout, dan context.Canceled ke "client is gone" (sering tanpa body respons).

func writeError(w http.ResponseWriter, ctx context.Context, err error) {
	if errors.Is(err, context.DeadlineExceeded) {
		http.Error(w, "request timed out", http.StatusGatewayTimeout)
		return
	}
	if errors.Is(err, context.Canceled) {
		// Client went away. Avoid doing more work.
		return
	}
	http.Error(w, "internal error", http.StatusInternalServerError)
}

Pola ini mencegah penumpukan. Setelah timer habis, setiap fungsi yang sadar context di down-chain mendapatkan sinyal berhenti yang sama dan bisa keluar cepat.

Propagasikan deadline ke panggilan PostgreSQL

Setelah handler Anda punya context dengan deadline, aturan terpenting sederhana: gunakan ctx yang sama hingga panggilan database. Begitulah cara timeout menghentikan pekerjaan alih-alih hanya menghentikan handler dari menunggu.

Dengan database/sql, pilih metode yang sadar context:

func (s *Server) getUser(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()

    row := s.db.QueryRowContext(ctx,
        "SELECT id, email FROM users WHERE id = $1",
        r.URL.Query().Get("id"),
    )

    var id int64
    var email string
    if err := row.Scan(&id, &email); err != nil {
        // handle below
    }
}

Pilih timeout DB yang sesuai anggaran request

Jika anggaran handler adalah 2 detik, database harus mendapat hanya sebagian dari itu. Sisakan waktu untuk encoding JSON, dependensi lain, dan penanganan error. Titik awal sederhana adalah memberi Postgres 30% sampai 60% dari total anggaran. Dengan deadline handler 2 detik, itu mungkin 800ms sampai 1.2s.

Apa yang terjadi saat Anda membatalkan query

Ketika context dibatalkan, driver meminta Postgres untuk menghentikan query. Biasanya koneksi kembali ke pool dan bisa dipakai ulang. Jika pembatalan terjadi saat momen jaringan buruk, driver mungkin membuang koneksi itu dan membuka koneksi baru nanti. Bagaimanapun, Anda menghindari goroutine yang menunggu selamanya.

Saat memeriksa error, perlakukan timeout berbeda dari kegagalan DB nyata. Jika errors.Is(err, context.DeadlineExceeded), Anda kehabisan waktu dan harus mengembalikan timeout. Jika errors.Is(err, context.Canceled), klien pergi dan Anda harus berhenti dengan tenang. Error lain adalah masalah query normal (SQL salah, baris hilang, izin).

Propagasikan deadline ke panggilan HTTP eksternal

Pertahankan kontrol penuh kode
Ekspor source dan terapkan middleware sendiri untuk deadline, log, dan pemetaan error.
Ekspor Kode

Jika handler Anda punya deadline, panggilan HTTP keluar harus menghormatinya juga. Kalau tidak, klien menyerah, tapi server Anda terus menunggu upstream yang lambat dan mengikat goroutine, socket, dan memori.

Buat request outbound dengan context induk sehingga pembatalan mengalir otomatis:

func fetchUser(ctx context.Context, url string) ([]byte, error) {
	// Add a small per-call cap, but never exceed the parent deadline.
	ctx, cancel := context.WithTimeout(ctx, 800*time.Millisecond)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return nil, err
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close() // always close, even on non-200

	return io.ReadAll(resp.Body)
}

Timeout per-panggilan itu adalah jaring pengaman. Deadline induk tetap bos sebenarnya. Satu jam untuk seluruh permintaan, ditambah topi lebih kecil untuk langkah berisiko.

Juga atur timeout di level transport. Context membatalkan request, tetapi timeout transport melindungi Anda dari handshake lambat dan server yang tidak pernah mengirim header.

Satu detail yang menyengat tim: body respons harus ditutup di setiap jalur. Jika Anda keluar lebih awal (cek status code, error decode JSON, timeout context), tetap tutup body. Bocornya body bisa diam-diam menguras koneksi di pool dan berubah menjadi lonjakan latensi "acak".

Skenario konkret: API Anda memanggil penyedia pembayaran. Klien timeout setelah 2 detik, tetapi upstream macet selama 30 detik. Tanpa pembatalan request dan timeout transport, Anda terus membayar untuk tunggu 30 detik itu untuk setiap permintaan yang ditinggalkan.

Penganggaran timeout sepanjang permintaan

Satu permintaan biasanya menyentuh lebih dari satu hal yang lambat: kerja handler, query database, dan satu atau lebih API eksternal. Jika Anda memberi setiap langkah timeout yang longgar, total waktu diam-diam tumbuh hingga pengguna merasakan dan server menumpuk.

Penganggaran adalah perbaikan paling sederhana. Tetapkan satu deadline induk untuk seluruh permintaan, lalu berikan setiap dependensi irisan waktu yang lebih kecil. Deadline anak harus lebih awal daripada induk agar Anda gagal cepat dan masih punya waktu mengembalikan error bersih.

Aturan praktis yang berlaku di layanan nyata:

  • Pilih anggaran total dulu (misal, 2 detik untuk endpoint yang dilihat pengguna).
  • Sisakan buffer kecil untuk overhead handler dan formatting respons (misal, 100–200ms).
  • Bagi sisa waktu ke dependensi.
  • Jika Anda punya beberapa panggilan eksternal, batasi masing-masing alih-alih membiarkan satu mengambil seluruh anggaran.
  • Jika context induk hanya punya 120ms tersisa, jangan mulai panggilan dependensi yang biasanya butuh 300ms.

Hindari menumpuk timeout yang saling berantem. Jika context handler punya deadline 2 detik dan client HTTP Anda punya timeout 10 detik, Anda aman tetapi membingungkan. Jika sebaliknya, client mungkin memotong lebih awal karena alasan yang tidak terkait.

Untuk pekerjaan background (audit log, metric, email), jangan gunakan context request. Gunakan context terpisah dengan timeout singkat sehingga pembatalan klien tidak membunuh cleanup penting.

Kesalahan umum yang membuat permintaan tetap menggantung

Ajak tim Anda bergabung
Undang tim atau teman untuk membangun dengan Koder.ai dan dapatkan kredit melalui referral.
Refer Teman

Sebagian besar bug timeout bukan di handler. Mereka terjadi satu atau dua lapisan ke bawah, di mana deadline diam-diam hilang. Jika Anda menetapkan timeout di edge tapi mengabaikannya di tengah, Anda masih bisa berakhir dengan goroutine, query DB, atau panggilan HTTP yang terus berjalan setelah klien pergi.

Polanya yang sering muncul sederhana:

  • Menjatuhkan context request dan memanggil lapisan bawah dengan context.Background() (atau TODO). Itu memutus pekerjaan dari pembatalan klien dan deadline handler.
  • Sleep, retry, atau loop tanpa memeriksa ctx.Done(). Request dibatalkan, tetapi kode Anda terus menunggu.
  • Membungkus setiap helper dengan context.WithTimeout sendiri. Anda berakhir dengan banyak timer dan deadline yang membingungkan.
  • Lupa melampirkan ctx ke panggilan blocking (DB, HTTP outbound, publish message). Timeout handler tidak ada artinya jika panggilan dependensi mengabaikannya.
  • Memperlakukan timeout seperti kegagalan umum dan mengembalikan 500. Klien butuh sinyal jelas bahwa permintaan kehabisan waktu.

Kegagalan klasik: Anda menambahkan timeout 2 detik di handler, lalu repository Anda menggunakan context.Background() untuk query database. Saat beban, query lambat terus berjalan bahkan setelah klien menyerah, dan tumpukan tumbuh.

Perbaiki dasar: teruskan ctx sebagai argumen pertama melalui stack panggilan Anda. Di dalam pekerjaan panjang, tambahkan pemeriksaan cepat seperti select { case <-ctx.Done(): return ctx.Err() default: }. Pemetakan context.DeadlineExceeded ke respons timeout (sering 504) dan context.Canceled ke respons gaya pembatalan klien (sering 408 atau 499 tergantung konvensi Anda).

Menguji dan memantau timeout dalam praktik

Timeout hanya membantu kalau Anda bisa melihatnya terjadi dan memastikan sistem pulih dengan bersih. Ketika sesuatu lambat, permintaan harus berhenti, sumber daya harus dilepas, dan API harus tetap responsif.

Log yang penting (dan buat konsisten)

Untuk setiap request, log set kecil field yang sama sehingga Anda bisa membandingkan request normal vs timeout. Sertakan deadline context (jika ada) dan apa yang mengakhiri pekerjaan.

Field berguna meliputi deadline (atau "none"), total elapsed time, alasan pembatalan (timeout vs client canceled), label operasi singkat ("db.query users", "http.call billing"), dan request ID.

Polanya minimal terlihat seperti ini:

start := time.Now()
deadline, hasDeadline := ctx.Deadline()
err := doWork(ctx)
log.Printf("op=%s hasDeadline=%t deadline=%s elapsed=%s err=%v",
  "getUser", hasDeadline, deadline.Format(time.RFC3339Nano), time.Since(start), err)

Metrik yang menunjukkan timeout sebelum pengguna keluhkan

Log membantu debug satu permintaan. Metrik menunjukkan tren.

Lacak beberapa sinyal yang biasanya melonjak lebih awal saat timeout salah: jumlah timeout per route dan dependensi, request in-flight (seharusnya stabil di bawah beban), waktu menunggu pool DB, dan persentil latensi (p95/p99) yang dipisah berdasarkan sukses vs timeout.

Reproduksi timeout secara lokal (supaya Anda percaya perbaikannya)

Buat kelambatan jadi bisa diprediksi. Tambahkan delay debug-only ke satu handler, perlambat query DB dengan penantian sengaja, atau bungkus panggilan eksternal dengan server test yang tidur. Lalu verifikasi dua hal: Anda melihat error timeout, dan pekerjaan berhenti tak lama setelah pembatalan.

Tes beban kecil juga membantu. Jalankan 20–50 request bersamaan selama 30–60 detik dengan satu dependensi yang dipaksa lambat. Jumlah goroutine dan request in-flight harus naik lalu stabil. Jika terus naik, sesuatu mengabaikan pembatalan context.

Daftar periksa cepat sebelum rilis

Timeout hanya membantu jika diterapkan di mana pun sebuah request bisa menunggu. Sebelum deploy, lakukan satu kali peninjauan kode dan pastikan aturan yang sama diikuti di setiap handler.

  • Setiap request masuk punya anggaran waktu jelas di boundary (router, middleware, handler). Tidak ada handler tak terbatas.
  • Setiap query database menerima context request (atau child context) dan memeriksa error untuk context.DeadlineExceeded dan context.Canceled.
  • Setiap panggilan HTTP keluar menggunakan http.NewRequestWithContext (atau req = req.WithContext(ctx)) dan client punya timeout transport (dial, TLS, response header). Hindari bergantung pada http.DefaultClient di jalur produksi.
  • Error dipetakan konsisten: timeout menjadi respons API yang sama tiap kali (sering 504), pembatalan klien dipetakan bersih (sering 499 atau 408 tergantung konvensi), dan timeout internal tidak membocorkan error driver mentah.
  • Log dan metrik membuat timeout jelas: nama handler, elapsed time, dan dependensi mana yang timeout.

Latihan singkat "dependensi lambat" sebelum rilis sangat berharga. Tambahkan delay buatan 2 detik ke satu query SQL dan konfirmasi tiga hal: handler mengembalikan tepat waktu, panggilan DB benar-benar berhenti (bukan hanya handler), dan log Anda jelas menyatakan itu adalah timeout DB.

Contoh realistis: satu request, tiga dependensi lambat

Uji dengan domain nyata
Set domain kustom untuk app yang dideploy agar memvalidasi perilaku timeout gateway dan edge.
Tambahkan Domain

Bayangkan endpoint seperti GET /v1/account/summary. Satu aksi user memicu tiga hal: query PostgreSQL (account plus aktivitas terbaru) dan dua panggilan HTTP eksternal (misal, pemeriksaan status billing dan lookup enrichment profil).

Berikan seluruh request anggaran keras 2 detik. Tanpa anggaran, satu dependensi lambat bisa mengikat goroutine, koneksi DB, dan memori sampai API Anda mulai timeout di mana-mana.

Pemecahan sederhana mungkin 800ms untuk query DB, 600ms untuk panggilan eksternal A, dan 600ms untuk panggilan eksternal B.

Setelah Anda tahu deadline keseluruhan, teruskan itu ke bawah. Setiap dependensi mendapat timeout lebih kecil sendiri, tapi tetap mewarisi pembatalan dari induk.

func AccountSummary(w http.ResponseWriter, r *http.Request) {
  ctx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
  defer cancel()

  dbCtx, dbCancel := context.WithTimeout(ctx, 800*time.Millisecond)
  defer dbCancel()

  aCtx, aCancel := context.WithTimeout(ctx, 600*time.Millisecond)
  defer aCancel()

  bCtx, bCancel := context.WithTimeout(ctx, 600*time.Millisecond)
  defer bCancel()

  // Use dbCtx for QueryContext, aCtx/bCtx for outbound HTTP requests.
}

Jika panggilan eksternal B melambat dan butuh 2.5 detik, handler Anda harus berhenti menunggu pada 600ms, membatalkan pekerjaan in-flight, dan mengembalikan respons timeout yang jelas ke klien. Klien melihat kegagalan cepat alih-alih spinner yang menggantung.

Log Anda harus membuatnya jelas apa yang memakai anggaran, misalnya: DB selesai cepat, eksternal A sukses, eksternal B mencapai batasnya dan mengembalikan context deadline exceeded.

Langkah berikutnya: standarkan timeout di seluruh API

Setelah satu endpoint nyata bekerja baik dengan timeout dan pembatalan, ubah itu menjadi pola yang bisa diulang. Terapkan end-to-end: deadline handler, panggilan DB, dan HTTP outbound. Lalu salin struktur yang sama ke endpoint berikutnya.

Anda akan bergerak lebih cepat jika memusatkan bagian membosankan: helper timeout boundary, wrapper yang memastikan ctx diteruskan ke panggilan DB dan HTTP, serta satu pemetaan error dan format log yang konsisten.

Jika Anda ingin mencoba pola ini dengan cepat, Koder.ai (koder.ai) dapat menghasilkan handler Go dan panggilan service dari prompt chat, dan Anda bisa mengekspor source code untuk menerapkan helper timeout dan anggaran sendiri. Tujuannya adalah konsistensi: panggilan lambat berhenti lebih awal, error terlihat sama, dan debugging tidak tergantung siapa yang menulis endpoint.

Pertanyaan umum

Mengapa beberapa permintaan lambat bisa menjatuhkan API yang sebenarnya sehat?

Permintaan yang lambat menahan sumber daya terbatas saat menunggu: sebuah goroutine, memori untuk buffer dan objek respons, dan seringkali koneksi database atau koneksi client HTTP. Ketika cukup banyak permintaan menunggu bersamaan, antrean terbentuk, latensi meningkat untuk seluruh lalu lintas, dan layanan bisa gagal meskipun setiap permintaan pada akhirnya akan selesai.

Apa cara paling sederhana untuk mencegah permintaan lambat menumpuk di Go?

Tetapkan batas waktu yang jelas di batas permintaan (proxy/gateway dan di server Go), turunkan context ber-waktu di handler, dan teruskan ctx itu ke setiap panggilan yang melakukan blocking (database dan HTTP keluar). Saat batas waktu tercapai, kembalikan segera dengan respons timeout yang konsisten dan hentikan pekerjaan in-flight yang mendukung pembatalan.

Kapan saya harus menggunakan WithTimeout vs WithDeadline vs WithCancel?

Gunakan context.WithTimeout(parent, d) ketika Anda ingin “berhenti setelah durasi ini,” yang paling umum di handler. Gunakan context.WithDeadline(parent, t) jika Anda sudah punya waktu cutoff tertentu yang harus dipatuhi. Gunakan context.WithCancel(parent) ketika kondisi internal harus menghentikan pekerjaan lebih awal, seperti “kita sudah punya jawaban” atau “klien terputus.”

Mengapa saya perlu memanggil cancel() jika timeout akan terjadi juga?

Selalu panggil fungsi cancel, biasanya dengan defer cancel() segera setelah membuat context turunan. Membatalkan melepaskan timer dan memberi sinyal berhenti yang jelas ke pekerjaan anak, terutama pada jalur kode yang keluar lebih awal sebelum deadline terpenuhi.

Bagaimana caranya memastikan deadline benar-benar sampai ke lapisan bawah?

Buat context request sekali di handler dan teruskan sebagai argumen pertama ke fungsi yang mungkin blocking. Cara cepat mengecek: cari context.Background() atau context.TODO() di jalur kode request; itu sering memutus propagasi pembatalan dan deadline.

Bagaimana cara menerapkan timeout pada query PostgreSQL dengan benar?

Gunakan metode database yang sadar context seperti QueryContext, QueryRowContext, dan ExecContext (atau ekuivalennya di driver Anda). Ketika context berakhir, driver dapat meminta PostgreSQL untuk membatalkan query sehingga Anda tidak terus membakar waktu dan koneksi setelah permintaan selesai.

Bagaimana cara menghentikan panggilan HTTP keluar yang menggantung setelah klien menyerah?

Lampirkan context request induk ke request outbound menggunakan http.NewRequestWithContext(ctx, ...), dan juga konfigurasikan timeout client/transport sehingga Anda terlindungi selama koneksi, TLS, dan menunggu header respons. Bahkan saat error atau respons non-200, selalu tutup body respons agar koneksi kembali ke pool.

Bagaimana saya harus “menganggarkan” waktu untuk DB dan beberapa panggilan eksternal?

Pilih satu anggaran total untuk permintaan terlebih dulu, lalu berikan setiap dependensi potongan waktu yang lebih kecil yang muat di dalamnya, menyisakan buffer kecil untuk overhead handler dan encoding respons. Jika context induk hanya punya sedikit waktu tersisa, jangan mulai pekerjaan mahal yang tidak bisa selesai sebelum deadline.

Status code apa yang sebaiknya saya kembalikan untuk timeout dan pembatalan context?

Standar umum adalah memetakan context.DeadlineExceeded ke 504 Gateway Timeout dengan pesan singkat seperti “request timed out.” Untuk context.Canceled, biasanya berarti klien terputus; sering tindakan terbaik adalah menghentikan pekerjaan dan tidak menulis body, sehingga Anda tidak membuang sumber daya lebih lanjut.

Apa kesalahan paling umum yang membuat handler mengabaikan timeout?

Kesalahan paling umum adalah: mengganti context request dengan context.Background(), memulai retry atau sleep tanpa memeriksa ctx.Done(), dan lupa melampirkan ctx ke panggilan blocking. Isu lain yang halus adalah menumpuk banyak timeout yang tidak terkait di berbagai tempat, yang membuat kegagalan sulit ditafsirkan dan dapat menyebabkan pemutusan lebih awal yang mengejutkan.

Daftar isi
Mengapa permintaan lambat bisa melemahkan APITimeout context dalam istilah sederhanaTetapkan batas waktu di boundary APILangkah demi langkah: tambahkan timeout ke handler HTTPPropagasikan deadline ke panggilan PostgreSQLPropagasikan deadline ke panggilan HTTP eksternalPenganggaran timeout sepanjang permintaanKesalahan umum yang membuat permintaan tetap menggantungMenguji dan memantau timeout dalam praktikDaftar periksa cepat sebelum rilisContoh realistis: satu request, tiga dependensi lambatLangkah berikutnya: standarkan timeout di seluruh APIPertanyaan umum
Bagikan
Koder.ai
Buat aplikasi sendiri dengan Koder hari ini!

Cara terbaik untuk memahami kekuatan Koder adalah melihatnya sendiri.

Mulai GratisPesan Demo