Meningkatkan kapasitas dan kecepatan aplikasi Flask: memilih worker Gunicorn sync vs gevent, connection pooling untuk database, caching strategis, load testing dengan alat bantu, dan optimasi berbasis data bukan tebakan.

Aplikasi kalian jalan, test lulus, deploy sukses — lalu apa? Trafik naik, dan halaman mulai lambat. Episode 24 membahas scaling & performance: bagaimana aplikasi Flask menangani lebih banyak request, dan di mana bottleneck sebenarnya. Kunci utama episode ini: optimasi berdasarkan data, bukan tebakan — ukur dulu, baru ubah.
Kita akan membahas worker Gunicorn, connection pooling, caching strategis, dan load testing.
Dua arah pertumbuhan:
| Strategi | Cara | Kapan |
|---|---|---|
| Scaling vertikal | Perbesar satu mesin (RAM, CPU) | Sederhana; cepat untuk single bottleneck |
| Scaling horizontal | Tambah instance aplikasi (lebih banyak worker/container) | Trafik tinggi; butuh shared state (DB, cache) |
Untuk Flask, titik awal yang tepat: lebih banyak worker Gunicorn (scaling horizontal di satu mesin), lalu tambah mesin/container dengan load balancer saat satu mesin penuh. Kedua arah membutuhkan pemahaman worker model — topik pertama kita.
Dari episode 22, tipe worker menentukan cara aplikasi memproses request paralel:
gunicorn --workers 4 --bind 127.0.0.1:8000 "app:create_app()"
gunicorn --workers 2 --threads 8 --bind 127.0.0.1:8000 "app:create_app()"
gunicorn --worker-class gevent --workers 8 --bind 127.0.0.1:8000 "app:create_app()"sync: satu worker = satu request pada satu waktu. Jika view menunggu I/O (DB, API eksternal), worker "menganggur" menunggu — kapasitas terbuang. Butuh banyak worker.gthread: threads dalam worker menangani beberapa request bersamaan — cocok untuk I/O yang lambat tanpa overhead proses penuh.gevent: green threads (cooperative scheduling) — ribuan koneksi "bersamaan" dalam satu worker untuk workload I/O-bound.Pilih berdasarkan profil aplikasi:
CPU-bound (komputasi berat) -> sync, jumlah worker = CPU cores
I/O-bound (DB, jaringan) -> gthread/gevent
Campuran -> gthread dengan threads sedangUji dengan load test (di bawah) untuk memutuskan — jangan menebak.
Note
Flask adalah framework sinkron — view biasa memblokir. Jika aplikasi kalian banyak menunggu API eksternal (integrasi payment, webhook), gevent memberi keuntungan besar tanpa menulis ulang kode. Namun pastikan library jaringan yang dipakai kompatibel dengan monkey-patching gevent — kode blocking lama justru akan melambat atau macet.
Setiap worker membuka koneksi database — membuka koneksi baru per request sangat mahal. Connection pooling menyimpan kumpulan koneksi yang dipakai ulang:
class ProductionConfig(BaseConfig):
SQLALCHEMY_ENGINE_OPTIONS = {
"pool_size": 10, # koneksi siap pakai
"max_overflow": 20, # tambahan saat ramai
"pool_pre_ping": True, # cek koneksi sebelum dipakai
"pool_recycle": 3600, # buang koneksi berumur > 1 jam
}pool_size: koneksi yang dijaga tetap terbuka.pool_pre_ping: memeriksa koneksi sebelum query — menghindari error "connection lost" setelah DB restart.pool_recycle: membuang koneksi yang umurnya melebihi timeout server (PostgreSQL default 1 jam).Untuk SQLite, pooling hampir tidak relevan (file-based, single writer) — inilah alasan lain produksi memakai PostgreSQL (episode 10).
Dari episode 15, caching adalah senjata paling cepat mengurangi beban. Pola yang paling berdampak:
class ProductionConfig(BaseConfig):
CACHE_TYPE = "RedisCache"
CACHE_REDIS_URL = os.environ.get("REDIS_URL")
CACHE_DEFAULT_TIMEOUT = 300Urutan pengoptimalan yang disarankan: (1) ukur, (2) cache yang paling murah & paling sering dipakai, (3) optimasi query, (4) baru sentuh worker. Biasanya 80% perbaikan datang dari 20% endpoint yang paling panas.
Optimasi tanpa pengukuran adalah tebakan. Load testing mensimulasikan beban request untuk menemukan bottleneck nyata. Alat populer: hey, wrk, k6, locust. Contoh dengan hey:
hey -n 10000 -c 100 http://127.0.0.1:8000/api/users-n 10000 — total 10.000 request.-c 100 — 100 request bersamaan (concurrency).Output yang perlu diperhatikan:
Total: 12.4 secs
Requests/sec: 806.45
Latency: 99.9% ... 0.284 secsMetodologi yang benar: baseline dulu (tanpa optimasi), ubah satu variabel (misal worker type), ukur lagi, bandingkan. Satu perubahan per pengukuran.
Worker dan cache tidak membantu jika database adalah sumbunya. Beberapa query anti-pattern:
# BERBAHAYA: 1 query untuk 100 posts + 100 query untuk author
for post in posts:
print(post.author.name) # trigger query per post
# AMAN: eager load sekali
from sqlalchemy.orm import selectinload
posts = db.session.scalars(
db.select(Post).options(selectinload(Post.author))
).all()N+1 query — satu query list + query per baris — adalah penyebab "API terasa lambat" paling umum. selectinload/joinedload (episode 10) menggabungkan jadi dua query. Daftar periksa cepat:
gthread/gevent.Pada episode 24 ini, kalian telah belajar menaikkan kapasitas dan kecepatan aplikasi.
Inti yang harus dibawa pulang:
sync untuk CPU-bound, gthread/gevent untuk I/O-bound.pool_size, pool_pre_ping) untuk PostgreSQL.Di episode 25 selanjutnya, kita melihat peta besar: ekosistem & tren modern 2026 — Flask 3.1.3 dengan Werkzeug 3.1, perbandingan mendalam Django vs FastAPI, dan kapan memilih Flask. Sampai jumpa di episode 25!