Pada episode ini kita akan mempercepat transfer: menjalankan banyak request secara paralel dengan --parallel, memanfaatkan multiplexing HTTP/2 dan keep-alive, mengaktifkan kompresi, serta mengukur performa tiap request dengan write-out.

Di episode 14 kalian melihat bagaimana HTTP/2 dan HTTP/3 mengurangi waktu menunggu di level protokol. Sekarang pertanyaannya bergeser: bagaimana cara memanfaatkan kemampuan itu untuk membuat seluruh batch pekerjaan selesai lebih cepat? Jawabannya ada di dua tempat: paralelisme — menjalankan banyak transfer bersamaan — dan optimasi transfer — memastikan setiap byte berjalan seefisien mungkin, lalu membuktikannya dengan angka. Episode 15 ini adalah tentang kecepatan yang diukur, bukan dirasakan.
--parallel dan --parallel-maxCara naif untuk mengambil banyak URL adalah loop: satu request selesai, baru request berikutnya berangkat. Waktu totalnya adalah penjumlahan semua waktu request — dan sementara satu request menunggu respons server, koneksi dan CPU menganggur.
--parallel (alias -Z) mengubah itu: curl menjalankan semua URL secara bersamaan dalam satu proses, dengan koneksi yang dibatasi oleh --parallel-max (default 50):
curl -Z -o /dev/null \
https://api.example.com/users \
https://api.example.com/posts \
https://api.example.com/comments \
https://api.example.com/orders \
https://api.example.com/productscurl -Z --parallel-max 10 -o /dev/null \
https://api.example.com/users \
https://api.example.com/posts \
https://api.example.com/commentsBayangkan satu kasir melayani lima antrean sekaligus alih-alih satu per satu. Selama request-request itu independen — tidak ada yang bergantung pada hasil yang lain — paralelisme memangkas waktu eksekusi secara drastis tanpa menulis satu baris logika threading pun.
Tip
Default curl mengelompokkan transfer paralel secara berurutan-demi-host agar bisa memakai kembali koneksi. Untuk memulai semua transfer secepat mungkin, tambahkan --parallel-immediate — berguna saat kalian mengambil banyak file dari host yang berbeda-beda dan ingin semua koneksi terbuka langsung.
Paralelisme di atas bekerja bahkan dengan HTTP/1.1 — curl membuka banyak koneksi. Tapi dengan HTTP/2, ada lapisan kedua: semua URL ke host yang sama berbagi satu koneksi TCP lewat multiplexing. Setiap URL menjadi stream di dalam koneksi yang sama, berjalan paralel tanpa perlu membuka koneksi baru.
curl -Z https://api.example.com/users https://api.example.com/postsMengapa ini penting? Setiap koneksi TCP baru berarti handshake baru — terutama handshake TLS dari episode 12 yang mahal. Multiplexing HTTP/2 menghilangkan biaya itu untuk batch yang menuju host sama. Inilah kombinasi paling hemat: -Z untuk paralelisme antar URL, HTTP/2 untuk berbagi satu koneksi di belakangnya.
Dari episode 11 kalian tahu curl memakai kembali koneksi untuk URL ke host yang sama dalam satu perintah. Ini bekerja dengan keep-alive HTTP: koneksi tidak ditutup setelah satu request, melainkan dipertahankan untuk request berikutnya.
Kebiasaan yang sering membuang keuntungan ini: memanggil curl berulang kali dalam satu proses per request. Setiap pemanggilan adalah startup proses baru, koneksi baru, dan handshake TLS baru. Jika skrip kalian memanggil curl sepuluh kali ke host yang sama, kalian membayar sepuluh kali biaya handshake — padahal cukup sekali.
# Beda: satu proses, satu koneksi, semua URL berbagi keep-alive
curl -o a.json https://api.example.com/a \
-o b.json https://api.example.com/b \
-o c.json https://api.example.com/cJika skrip harus tetap memanggil curl berkali-kali, minimal gabungkan ke satu pemanggilan dengan banyak -o — atau serahkan ke --parallel yang menangani manajemen koneksinya.
Secara default, curl mengumpulkan (buffer) data yang ditulis ke terminal atau pipe — berguna untuk menjaga output tetap utuh. Tapi untuk streaming — misalnya mengikuti log real-time atau menyalurkan respons panjang ke proses lain — buffering membuat data tertahan dan datang mengejut-kejut.
Opsi -N (alias --no-buffer) mematikan buffering, sehingga data mengalir begitu tiba:
curl -N https://api.example.com/eventscurl -N https://api.example.com/events | while read -r line; do
echo "[event] $line"
doneAturan praktisnya: untuk download biasa biarkan buffering default; untuk streaming dan pipeline yang butuh data seketika, pakai -N.
--compressedResponse HTTP sering berupa teks — JSON, HTML, atau log — yang sangat bisa ditekan. Tanpa kompresi, kalian mengunduh lebih banyak byte dari yang perlu. --compressed meminta server mengirim versi terkompresi dan men-dekompres-nya secara otomatis:
curl --compressed https://api.example.com/reports/big.jsoncurl mengirim header Accept-Encoding: deflate, gzip dan — jika build-nya mendukung — br (brotli) dan zstd juga ikut dalam daftar. Server yang mendukung mengirim respons terkompresi, dan curl membongkarnya sebelum menuliskannya ke output.
curl --versionCek kata brotli dan zstd di baris Features untuk melihat algoritma yang didukung build kalian. Untuk API yang mengembalikan JSON besar, kompresi sering memangkas ukuran transfer hingga 70-80% — angka yang langsung terlihat di -w.
Warning
Ada jebakan halus: jika kalian mengatur header Accept-Encoding sendiri secara manual, curl tidak akan men-dekompres responsnya — dekompresi otomatis hanya terjadi lewat --compressed. Jangan mencampur keduanya kecuali kalian tahu persis apa yang sedang kalian lakukan.
-wSemua optimasi di atas tidak ada artinya tanpa bukti. Opsi -w (write-out) dari episode 6 dan 18 bukan cuma untuk debugging — ia adalah benchmark satu baris yang bisa dibandingkan antar konfigurasi. Kumpulkan variabel kunci dalam satu format:
curl -s -o /dev/null -w "HTTP %{http_code} | DNS %{time_namelookup}s | Koneksi %{time_connect}s | TLS %{time_appconnect}s | Byte pertama %{time_starttransfer}s | Total %{time_total}s | %{size_download} bytes | %{speed_download} B/s\n" \
https://api.example.com/healthVariabel penting untuk pengukuran performa:
| Variabel | Apa yang diukur |
|---|---|
time_namelookup | Resolusi DNS |
time_connect | Handshake TCP |
time_appconnect | Handshake TLS selesai |
time_starttransfer | Sampai byte pertama respons |
time_total | Total seluruh transfer |
size_download | Ukuran data yang diterima |
speed_download | Kecepatan transfer rata-rata |
num_connects | Berapa koneksi yang dibuat |
Perhatikan pola diagnosisnya: time_appconnect yang tinggi menunjuk ke TLS (episode 12), time_starttransfer yang tinggi menunjuk ke server yang lambat merespons, dan size_download yang menyusut drastis dengan --compressed adalah bukti kompresi bekerja.
Mari rangkai semuanya menjadi percobaan yang bisa diulang: bandingkan lima request berurutan melawan lima request paralel, ke host yang sama.
curl -s -o /dev/null -w "%{time_total}\n" \
https://api.example.com/users https://api.example.com/posts \
https://api.example.com/comments https://api.example.com/orders \
https://api.example.com/productscurl -Z -s -o /dev/null -w "%{time_total}\n" \
https://api.example.com/users https://api.example.com/posts \
https://api.example.com/comments https://api.example.com/orders \
https://api.example.com/productsJalankan keduanya beberapa kali dan bandingkan. Pada batch ke host yang sama, HTTP/2 multiplexing membuat versi paralel terasa dramatis lebih cepat — dan selisihnya adalah angka yang bisa kalian bawa ke rapat ketika menjelaskan kenapa skrip harus dirombak. Optimasi tanpa pengukuran hanyalah opini; dengan -w, kalian punya data.
Episode 15 melengkapi kalian dengan kit performa lengkap: paralelisme dengan -Z dan --parallel-max, multiplexing HTTP/2 yang berbagi satu koneksi, reuse koneksi dan keep-alive yang menghilangkan handshake berulang, buffering dengan -N untuk streaming, kompresi dengan --compressed (gzip, brotli, zstd), serta pengukuran performa dengan -w yang membuktikan setiap optimasi.
Inti yang perlu diingat: kecepatan bukan soal mengetik lebih cepat, tapi soal menghilangkan waktu yang terbuang. Handshake yang diulang, byte yang tidak terkompresi, dan request yang menunggu giliran adalah pemborosan yang bisa diukur — dan sekarang kalian tahu cara menghilangkannya sekaligus membuktikannya.
Di episode 16 berikutnya kita akan mengubah semua kemampuan ini menjadi mesin: scripting dan automation — exit code, output yang bisa diurai, pipeline curl dengan jq, serta integrasi curl ke dalam CI/CD. Sampai jumpa!