Mencegah timeout ekspor: pekerjaan asinkron, progres, streaming
Cegah timeout ekspor dengan pekerjaan ekspor asinkron, indikator progres, paginasi, dan unduhan streaming untuk laporan CSV dan PDF berukuran besar.

Mengapa ekspor mengalami timeout, dalam istilah sederhana
Ekspor mengalami timeout ketika server tidak menyelesaikan pekerjaan sebelum batas waktu. Batas ini bisa ditetapkan oleh browser, reverse proxy, server aplikasi, atau koneksi basis data. Bagi pengguna sering terasa acak, karena ekspor kadang berhasil dan kadang gagal.
Di layar, biasanya terlihat seperti salah satu ini:
- Spinner yang tak kunjung berhenti
- Unduhan yang mulai lalu berhenti dengan "network error"
- Halaman error setelah menunggu lama
- File yang terunduh tetapi kosong atau rusak
Ekspor besar membuat stres karena mereka menyentuh beberapa bagian sistem sekaligus. Basis data harus menemukan dan mengumpulkan banyak baris. Server aplikasi harus memformatnya ke CSV atau merender ke PDF. Lalu browser harus menerima respons besar tanpa koneksi putus.
Dataset sangat besar jelas menjadi pemicu, tetapi ekspor “kecil” juga bisa berat. Join yang mahal, banyak field yang dihitung, lookup per-baris, dan filter tanpa indeks dapat mengubah laporan normal menjadi timeout. PDF sangat berisiko karena melibatkan layout, font, gambar, pemisahan halaman, dan sering query tambahan untuk mengumpulkan data terkait.
Percobaan ulang sering memperburuk keadaan. Ketika pengguna me-refresh atau menekan Ekspor lagi, sistem Anda mungkin memulai pekerjaan yang sama dua kali. Sekarang basis data menjalankan query duplikat, server aplikasi membuat file duplikat, dan Anda mendapat lonjakan tepat saat sistem sedang kesulitan.
Jika ingin mencegah timeout ekspor, perlakukan ekspor seperti tugas latar belakang, bukan pemuatan halaman biasa. Bahkan di pembuat no-code seperti AppMaster, pola alurnya lebih penting daripada alat: pekerjaan panjang butuh alur berbeda dari "klik tombol, tunggu respons."
Pilih pola ekspor yang tepat untuk aplikasi Anda
Sebagian besar kegagalan ekspor terjadi karena aplikasi menggunakan satu pola untuk semua situasi, padahal ukuran data dan waktu proses sangat bervariasi.
Ekspor sinkron sederhana (pengguna klik, server menghasilkan, unduhan dimulai) baik ketika ekspor kecil dan dapat diprediksi. Pikirkan beberapa ratus baris, kolom dasar, tanpa format berat, dan tidak banyak pengguna yang melakukannya bersamaan. Jika konsisten selesai dalam beberapa detik, yang sederhana biasanya terbaik.
Untuk apa pun yang lama atau tidak terduga, gunakan pekerjaan ekspor asinkron. Ini cocok untuk dataset besar, perhitungan kompleks, pekerjaan layout PDF, dan server bersama di mana satu ekspor lambat bisa memblokir permintaan lain.
Pekerjaan asinkron lebih cocok ketika:
- Ekspor sering memakan waktu lebih dari 10–15 detik
- Pengguna meminta rentang tanggal lebar atau "all time"
- Anda menghasilkan PDF dengan chart, gambar, atau banyak halaman
- Beberapa tim mengekspor pada jam sibuk
- Anda butuh retry aman saat terjadi kegagalan
Unduhan streaming juga membantu ketika ekspor besar tapi bisa dihasilkan secara berurutan. Server mulai mengirim byte segera, terasa lebih cepat dan menghindari membangun seluruh file di memori. Bagus untuk unduhan CSV panjang, tapi kurang membantu jika Anda harus menghitung semuanya sebelum menulis baris pertama.
Anda bisa menggabungkan pendekatan: jalankan job asinkron untuk menghasilkan ekspor (atau menyiapkan snapshot), lalu streaming unduhan saat siap. Di AppMaster, pendekatan praktis adalah membuat record "Export Requested", menghasilkan file dalam business process backend, dan biarkan pengguna mengunduh hasil jadi tanpa mempertahankan permintaan browser mereka tetap terbuka.
Langkah demi langkah: bangun pekerjaan ekspor asinkron
Perubahan terbesar sederhana: hentikan menghasilkan file di dalam permintaan yang sama saat pengguna menekan tombol.
Job ekspor asinkron memecah pekerjaan menjadi dua bagian: permintaan cepat yang membuat job, dan kerja latar belakang yang membangun file sementara aplikasi tetap responsif.
Alur praktis 5 langkah
- Tangkap permintaan ekspor (siapa yang meminta, filter, kolom terpilih, format output).
- Buat record job dengan status (queued, running, done, failed), timestamp, dan field error.
- Jalankan pekerjaan berat di latar belakang menggunakan queue, worker terjadwal, atau proses worker tersendiri.
- Tulis hasil ke storage (object storage atau file store), lalu simpan referensi download di record job.
- Beri tahu pengguna saat siap menggunakan notifikasi in-app, email, atau saluran pesan yang tim Anda pakai.
Pertahankan record job sebagai sumber kebenaran. Jika pengguna me-refresh, pindah perangkat, atau menutup tab, Anda tetap bisa menunjukkan status job yang sama dan tombol unduhan yang sama.
Contoh: manajer dukungan mengekspor semua tiket kuartal lalu. Alih-alih menunggu tab berputar, mereka melihat entry job berpindah dari queued ke done, lalu unduhan muncul. Di AppMaster, Anda bisa memodelkan tabel job di Data Designer, membangun logika latar belakang di Business Process Editor, dan gunakan field status untuk mengendalikan state UI.
Indikator progres yang benar-benar dipercaya pengguna
Indikator progres yang baik mengurangi kecemasan dan menghentikan orang menekan Ekspor berkali-kali. Ini juga membantu mencegah timeout ekspor secara tidak langsung, karena pengguna lebih bersedia menunggu ketika aplikasi menunjukkan kemajuan nyata.
Tunjukkan progres dengan istilah yang dipahami orang. Persen sendiri sering menyesatkan, jadi padukan dengan sesuatu yang konkret:
- Langkah saat ini (Menyiapkan data, Mengambil baris, Membangun file, Mengunggah, Siap)
- Baris yang diproses dari total (atau halaman yang diproses)
- Waktu mulai dan terakhir diperbarui
- Perkiraan waktu tersisa (hanya jika cukup stabil)
Hindari presisi palsu. Jika Anda belum tahu total pekerjaan, jangan tampilkan 73%. Gunakan milestone dulu, lalu beralih ke persen ketika pembagi sudah diketahui. Pola sederhana: 0%–10% untuk setup, 10%–90% berdasarkan baris yang diproses, dan 90%–100% untuk finalisasi file. Untuk PDF dengan ukuran halaman variabel, lacak kebenaran kecil seperti "record yang dirender" atau "bagian selesai."
Perbarui cukup sering agar terasa hidup, tapi jangan terlalu sering hingga membebani basis data atau queue. Pendekatan umum: tulis progres setiap 1–3 detik, atau setiap N record (mis. setiap 500 atau 1.000 baris), mana yang lebih jarang. Juga simpan heartbeat timestamp ringan agar UI bisa menampilkan "Masih bekerja" meski persentase tidak bergerak.
Berikan pengguna kontrol saat proses lebih lama dari perkiraan. Biarkan mereka membatalkan ekspor yang berjalan, memulai yang baru tanpa kehilangan yang pertama, dan melihat riwayat ekspor dengan status (Queued, Running, Failed, Ready) plus pesan error singkat.
Di AppMaster, record tipikal seperti ExportJob (status, processed_count, total_count, step, updated_at). UI mem-poll record itu dan menampilkan progres jujur sementara job asinkron menghasilkan file di latar belakang.
Paginasi dan filtering untuk menjaga pekerjaan terbatas
Sebagian besar timeout ekspor terjadi karena ekspor mencoba melakukan semuanya sekaligus: terlalu banyak baris, kolom, join. Perbaikan tercepat adalah menjaga pekerjaan tetap terbatas sehingga pengguna mengekspor irisan data yang lebih kecil dan jelas.
Mulai dari tujuan pengguna. Jika seseorang butuh "faktur bulan lalu yang gagal," jangan default ke "semua faktur sepanjang masa." Buat filter terasa normal, bukan tugas tambahan. Rentang tanggal sederhana plus satu atau dua status kunci sering mengurangi dataset hingga 90%.
Formulir permintaan ekspor yang baik biasanya meliputi rentang tanggal (dengan default masuk akal seperti 7 atau 30 hari terakhir), satu atau dua status kunci, pencarian opsional atau pilihan customer/tim, dan pratinjau hitungan bila memungkinkan (bahkan perkiraan).
Di sisi server, baca data dalam potongan menggunakan paginasi. Ini menjaga memori stabil dan memberi checkpoint alami untuk progres. Selalu gunakan pengurutan stabil saat paging (mis. order by created_at, lalu id). Tanpa itu, baris baru bisa masuk ke halaman sebelumnya dan Anda akan kehilangan atau menduplikasi record.
Data berubah selama ekspor panjang, jadi tentukan apa yang dimaksud "konsisten." Pendekatan sederhana adalah merekam waktu snapshot saat job dimulai, lalu hanya mengekspor baris hingga timestamp itu. Jika butuh konsistensi ketat, gunakan consistent read atau transaksi jika basis data Anda mendukungnya.
Di alat no-code seperti AppMaster, ini cocok dengan business process: validasi filter, set snapshot time, lalu loop melalui halaman sampai tidak ada lagi yang diambil.
Streaming unduhan tanpa membebani server
Streaming berarti Anda mulai mengirim file ke pengguna saat Anda masih menghasilkan file. Server tidak perlu membangun seluruh CSV atau PDF di memori terlebih dahulu. Ini salah satu cara paling andal untuk mencegah timeout ketika file menjadi besar.
Streaming tidak serta merta membuat query lambat jadi cepat. Jika kerja basis data membutuhkan lima menit sebelum byte pertama siap, permintaan masih bisa timeout. Perbaikan umum adalah menggabungkan streaming dengan paging: ambil chunk, tulis, dan lanjutkan.
Untuk menjaga memori rendah, tulis sambil berjalan. Hasilkan satu chunk (mis. 1.000 baris CSV atau satu halaman PDF), tulis ke respons, lalu flush sehingga klien terus menerima data. Hindari mengumpulkan baris ke array besar "hanya untuk disortir nanti." Jika Anda butuh urutan stabil, sort di basis data.
Header, nama, dan content type
Gunakan header jelas agar browser dan aplikasi mobile memperlakukan unduhan dengan benar. Set content type yang tepat (mis. text/csv atau application/pdf) dan nama file yang aman. Nama file sebaiknya menghindari karakter khusus, pendek, dan menyertakan timestamp jika pengguna mengekspor laporan yang sama berkali-kali.
Melanjutkan dan unduhan parsial
Putuskan sejak awal apakah Anda mendukung resume. Streaming dasar sering tidak mendukung resume berbasis byte-range, terutama untuk PDF yang digenerasi. Jika mendukung, Anda harus menangani Range requests dan menghasilkan output konsisten untuk job yang sama.
Sebelum rilis, pastikan Anda:
- Mengirim header sebelum menulis body, lalu tulis dalam potongan dan flush
- Menjaga ukuran chunk stabil agar memori tetap datar di bawah beban
- Menggunakan ordering deterministik agar pengguna percaya hasilnya
- Mendokumentasikan apakah resume didukung dan apa yang terjadi jika koneksi putus
- Menambahkan batas sisi server (max rows, max time) dan mengembalikan error ramah saat terlampaui
Jika Anda membangun ekspor di AppMaster, simpan logika generasi di flow backend dan stream dari sisi server, bukan dari browser.
Ekspor CSV besar: taktik praktis
Untuk CSV besar, hentikan perlakuan file sebagai satu blob. Bangun sebagai loop: baca irisan data, tulis baris, ulangi. Itu menjaga memori datar dan membuat retry lebih aman.
Tulis CSV baris demi baris. Bahkan jika menghasilkan ekspor dalam job asinkron, hindari "kumpulkan semua baris, lalu stringify." Buka writer dan tambahkan tiap baris segera setelah siap. Jika stack Anda mendukung, gunakan cursor basis data atau paging melalui hasil sehingga Anda tidak pernah memuat jutaan record sekaligus.
Kebenaran CSV sama pentingnya dengan kecepatan. File bisa tampak baik sampai seseorang membukanya di Excel dan separuh kolom bergeser.
Aturan CSV yang mencegah file rusak
- Selalu escape koma, kutip, dan newline (bungkus seluruh field dalam kutip, dan gandakan kutip di dalamnya)
- Output UTF-8 dan uji nama non-Inggris end-to-end
- Gunakan header yang stabil dan jaga urutan kolom tetap sama antar-run
- Normalisasi tanggal dan desimal (pilih satu format dan gunakan konsisten)
- Hindari formula jika data bisa dimulai dengan =, +, -, atau @
Performa sering mati di akses data, bukan penulisan. Waspadai N+1 lookup (mis. memuat setiap customer dalam loop). Ambil data terkait dalam satu query, atau preload apa yang dibutuhkan, lalu tulis baris.
Saat ekspor benar-benar besar, pecah file dengan sengaja. Pendekatan praktis adalah satu file per bulan, per customer, atau per tipe entitas. Ekspor "5 tahun pesanan" bisa menjadi 60 file bulanan, masing-masing digenerasi terpisah, sehingga satu bulan lambat tidak memblokir semuanya.
Jika menggunakan AppMaster, model dataset di Data Designer dan jalankan ekspor sebagai business process latar belakang, menulis baris sambil paging melalui record.
Ekspor PDF besar: jaga agar dapat diprediksi
Generasi PDF biasanya lebih lambat daripada CSV karena CPU-heavy. Anda tidak hanya memindahkan data, tetapi juga menata halaman, meletakkan font, menggambar tabel, dan sering mengubah ukuran gambar. Perlakukan PDF sebagai tugas latar belakang dengan batas yang jelas, bukan respons cepat.
Pilihan template menentukan apakah ekspor 2 menit menjadi 20 menit. Layout sederhana menang: lebih sedikit kolom, lebih sedikit tabel bersarang, dan pemisahan halaman yang dapat diprediksi. Gambar adalah salah satu hal tercepat yang memperlambat semuanya, terutama jika beresolusi tinggi atau diambil dari storage remote saat rendering.
Keputusan template yang biasanya meningkatkan kecepatan dan keandalan:
- Gunakan satu atau dua font dan hindari rantai fallback yang berat
- Jaga header dan footer sederhana (hindari chart dinamis di setiap halaman)
- Pilih ikon vektor daripada gambar raster besar
- Batasi layout "auto fit" yang mengukur teks berkali-kali
- Hindari transparansi kompleks dan bayangan
Untuk ekspor besar, render secara batch. Hasilkan satu bagian atau rentang halaman kecil sekaligus, tulis ke file sementara, lalu gabungkan menjadi PDF akhir. Ini menjaga memori stabil dan membuat retry lebih aman jika worker crash di tengah jalan. Juga cocok dengan job asinkron dan progres yang bergerak di langkah bermakna (mis. "Menyiapkan data," "Merender halaman 1-50," "Finalisasi file").
Juga pertanyakan apakah PDF memang yang pengguna butuhkan. Jika mereka terutama ingin baris dan kolom untuk analisis, tawarkan CSV selain "Export PDF." Anda masih bisa membuat PDF ringkasan yang lebih kecil untuk laporan sambil menyimpan dataset lengkap di CSV.
Di AppMaster, ini cocok: jalankan generasi PDF sebagai job latar belakang, laporkan progres, dan kirim file jadi sebagai unduhan setelah job selesai.
Kesalahan umum yang menyebabkan timeout
Kegagalan ekspor biasanya tidak misterius. Beberapa pilihan bekerja baik dengan 200 baris, lalu runtuh pada 200.000.
Kesalahan paling umum:
- Menjalankan seluruh ekspor di dalam satu permintaan web. Browser menunggu, worker server sibuk, dan query lambat atau file besar mendorong Anda melewati batas waktu.
- Menampilkan progres berdasarkan waktu bukan pekerjaan. Timer yang melesat ke 90% lalu stagnan membuat pengguna me-refresh, membatalkan, atau memulai ekspor lagi.
- Membaca setiap baris ke memori sebelum menulis file. Mudah diimplementasikan, dan cara cepat mencapai batas memori.
- Menahan transaksi basis data lama atau mengabaikan lock. Query ekspor bisa memblokir penulisan, atau diblokir oleh penulisan, dan perlambatan itu menyebar ke aplikasi.
- Mengizinkan ekspor tak terbatas tanpa pembersihan. Klik berulang menumpuk job, memenuhi storage, dan meninggalkan file lama selamanya.
Contoh konkret: pemimpin support mengekspor semua tiket dua tahun terakhir dan menekan dua kali karena tak terlihat ada yang terjadi. Sekarang dua ekspor identik bersaing untuk basis data yang sama, keduanya membuat file besar di memori, dan keduanya timeout.
Jika membangun ini di alat no-code seperti AppMaster, aturan yang sama berlaku: jangan letakkan ekspor di jalur permintaan, lacak progres dengan baris yang diproses, tulis output sambil berjalan, dan beri batas sederhana berapa banyak ekspor yang boleh dijalankan sekaligus.
Pemeriksaan cepat sebelum rilis
Sebelum merilis fitur ekspor ke produksi, lakukan pemeriksaan cepat dengan pola pikir timer. Pekerjaan panjang berjalan di luar permintaan, pengguna melihat progres jujur, dan server tidak mencoba melakukan semuanya sekaligus.
Checklist pra-penerbangan:
- Ekspor besar dijalankan sebagai job latar belakang (yang kecil bisa sinkron jika konsisten cepat)
- Pengguna melihat status jelas seperti queued, running, done, atau failed, dengan timestamp
- Data dibaca dalam potongan dengan urutan stabil (mis. waktu dibuat plus ID sebagai tie-breaker)
- File yang selesai bisa diunduh nanti tanpa menjalankan ulang ekspor, meski pengguna menutup tab
- Ada batas dan rencana pembersihan untuk file lama dan riwayat job (penghapusan berdasarkan umur, max job per user, kuota storage)
Cek akal sehat: coba skenario terburuk Anda—ekspor rentang tanggal terbesar yang Anda izinkan saat orang lain aktif menambah record. Jika Anda melihat duplikat, baris hilang, atau progres macet, ordering atau chunking Anda tidak stabil.
Jika membangun di AppMaster, pemeriksaan ini sesuai dengan bagian nyata: proses latar belakang di Business Process Editor, record job di database, dan field status yang dibaca UI dan disegarkan.
Buat kegagalan terasa aman. Job yang gagal harus menyimpan pesan error, mengizinkan retry, dan menghindari membuat file parsial yang terlihat "selesai" tapi tidak lengkap.
Contoh: mengekspor data bertahun-tahun tanpa membekukan aplikasi
Seorang ops manager butuh dua ekspor setiap bulan: CSV dengan 2 tahun terakhir pesanan untuk analisis, dan sekumpulan PDF faktur bulanan untuk akuntansi. Jika aplikasi mencoba membangun salah satu selama permintaan web biasa, Anda akhirnya akan mencapai batas waktu.
Mulailah dengan membatasi pekerjaan. Layar ekspor meminta rentang tanggal (default: 30 hari terakhir), filter opsional (status, region, sales rep), dan pilihan kolom yang jelas. Perubahan itu sering mengubah masalah 2 tahun, 2 juta baris menjadi sesuatu yang dapat dikelola.
Saat pengguna menekan Ekspor, aplikasi membuat record Export Job (type, filters, requested_by, status, progress, error_text) dan memasukkannya ke queue. Di AppMaster, ini adalah model Data Designer plus Business Process yang berjalan di latar belakang.
Saat job berjalan, UI menunjukkan status yang dapat dipercaya: queued, processing (mis. 3 dari 20 chunk), generating file, ready (tombol unduh), atau failed (error jelas dan opsi retry).
Chunking adalah detail kunci. Job CSV membaca pesanan per halaman (mis. 50.000 sekaligus), menulis setiap halaman ke output, dan memperbarui progres setelah setiap chunk. Job PDF melakukan hal sama per batch faktur (mis. satu bulan), sehingga satu bulan lambat tidak memblokir semuanya.
Jika ada yang rusak (filter buruk, izin hilang, error storage), job ditandai Failed dengan pesan singkat yang bisa ditindaklanjuti pengguna: "Tidak dapat menghasilkan faktur Maret. Silakan coba lagi, atau hubungi support dengan Job ID 8F21." Retry menggunakan filter yang sama sehingga pengguna tidak perlu memulai dari awal.
Langkah selanjutnya: jadikan ekspor fitur bawaan, bukan kebakaran darurat
Cara tercepat mencegah timeout ekspor jangka panjang adalah berhenti memperlakukan ekspor sebagai tombol sekali pakai dan jadikan mereka fitur standar dengan pola berulang.
Pilih pendekatan default dan gunakan di mana-mana: job asinkron menghasilkan file di latar belakang, lalu pengguna mendapat opsi unduh saat file siap. Keputusan tunggal itu menghilangkan sebagian besar kejutan "berhasil di pengujian" karena permintaan pengguna tidak perlu menunggu file selesai.
Permudah orang menemukan apa yang sudah mereka buat. Halaman riwayat ekspor (per pengguna, per workspace, atau per akun) mengurangi ekspor ulang, membantu tim support menjawab "di mana file saya?", dan memberi tempat alami untuk menampilkan status, error, dan kadaluarsa.
Jika membangun pola ini di AppMaster, platform membantu karena menghasilkan kode sumber nyata dan mendukung logika backend, pemodelan database, serta UI web/mobile dalam satu tempat. Untuk tim yang ingin mengirim job ekspor asinkron andal dengan cepat, appmaster.io sering dipakai untuk membuat tabel job, proses latar belakang, dan UI progres tanpa menyambung semuanya secara manual.
Lalu ukur apa yang benar-benar menyakitkan. Lacak query basis data yang lambat, waktu yang dihabiskan menghasilkan CSV, dan waktu render PDF. Anda tidak perlu observabilitas sempurna untuk mulai: logging durasi dan hitungan baris per ekspor cepat menunjukkan laporan atau kombinasi filter mana yang menjadi masalah nyata.
Perlakukan ekspor seperti fitur produk lainnya: konsisten, terukur, dan mudah didukung.
FAQ
Sebuah ekspor mengalami timeout ketika pekerjaan tidak selesai sebelum batas waktu yang ditetapkan di jalur permintaan. Batas ini bisa berasal dari browser, reverse proxy, server aplikasi, atau koneksi basis data, sehingga terlihat acak meski penyebab dasarnya adalah beban konsisten atau query yang lambat.
Gunakan ekspor sinkron sederhana hanya jika selalu selesai dalam beberapa detik dengan ukuran data yang dapat diprediksi. Jika ekspor sering memakan waktu lebih dari 10–15 detik, melibatkan rentang tanggal besar, perhitungan berat, atau PDF, beralihlah ke job asinkron agar permintaan browser tidak perlu tetap terbuka.
Buat dulu record job, lalu lakukan pekerjaan berat di latar belakang, dan akhirnya biarkan pengguna mengunduh file yang sudah selesai. Di AppMaster, setup umum adalah model ExportJob di Data Designer ditambah Business Process backend yang memperbarui status, field progres, dan referensi file tersimpan saat berjalan.
Lacak pekerjaan nyata, bukan waktu yang berlalu. Pendekatan praktis adalah menyimpan field seperti step, processed_count, total_count (jika diketahui), dan updated_at, lalu biarkan UI mem-poll dan menunjukkan perubahan status agar pengguna tidak merasa terhenti dan menekan tombol ekspor berulang.
Buat permintaan ekspor idempoten dan jadikan record job sumber kebenaran. Jika pengguna menekan lagi, tampilkan job yang sedang berjalan (atau blok duplikat untuk filter yang sama) alih-alih memulai pekerjaan mahal yang sama dua kali.
Baca dan tulis dalam potongan sehingga memori tetap stabil dan Anda mendapatkan checkpoint alami. Gunakan paginasi stabil dengan urutan deterministik (mis. created_at lalu id) agar Anda tidak melewatkan atau menggandakan baris saat data berubah selama ekspor panjang.
Rekam waktu snapshot saat job dimulai dan ekspor hanya baris hingga timestamp itu agar output tidak “bergerak” selama proses. Jika Anda butuh jaminan lebih ketat, gunakan consistent reads atau strategi transaksi yang didukung basis data Anda, tetapi mulai dengan aturan snapshot yang mudah dipahami pengguna.
Streaming membantu saat Anda bisa menghasilkan output berurutan dan mulai mengirim byte lebih awal, terutama untuk CSV besar. Ia tidak akan memperbaiki query lambat yang butuh menit sebelum byte pertama tersedia, dan masih bisa timeout jika tidak ada yang ditulis untuk waktu lama. Jadi streaming paling efektif bila dikombinasikan dengan paging yang terus menulis potongan.
Tulis baris saat Anda menghasilkan dan ikuti escaping CSV yang benar agar file tidak rusak di Excel atau alat lain. Pertahankan encoding konsisten (biasanya UTF-8), header dan urutan kolom stabil, dan hindari lookup per-baris yang mengubah satu ekspor menjadi ribuan query tambahan.
Generasi PDF berat secara CPU karena melibatkan layout, font, gambar, dan pemisahan halaman. Perlakukan sebagai job latar belakang dengan batasan jelas. Sederhanakan template, hindari gambar besar atau mengambil gambar dari sumber remote saat rendering, dan laporkan progres dalam langkah bermakna agar pengguna tahu proses berjalan.


