Django Async Views dan ASGI pada 2026: Performa dan Pertanyaan Wawancara
Ulasan mendalam tentang Django async views dan ASGI pada 2026: cara kerjanya di balik layar, server mana yang di-deploy, ORM async dan jebakan SynchronousOnlyOperation, plus pertanyaan wawancara.

Django async views memungkinkan satu worker menangani ratusan request I/O-bound secara bersamaan tanpa mendedikasikan satu thread untuk tiap koneksi, tetapi hanya jika jalur kode tetap asynchronous mulai dari view hingga setiap panggilan jaringan. Sejak Django 3.1 memperkenalkan view async def dan Django 4.1 menambahkan antarmuka ORM async, framework ini telah menjadi platform ASGI yang kredibel, namun sebagian besar deployment produksi masih berjalan di WSGI dan membiarkan potensi konkurensi itu tidak tersentuh. Ulasan mendalam ini menjelaskan bagaimana async views berperilaku di ASGI, server mana yang layak dijalankan pada 2026, jebakan ORM yang memunculkan SynchronousOnlyOperation, serta pertanyaan wawancara yang membedakan engineer yang telah merilis Django async dari mereka yang hanya membacanya.
Async views memberi keuntungan ketika sebuah request menghabiskan sebagian besar waktunya menunggu I/O yang tidak dikendalikannya: API HTTP pihak ketiga, layanan downstream yang lambat, atau respons streaming berdurasi panjang. Untuk pekerjaan CPU-bound atau query database lokal yang cepat, view sinkron yang didukung lebih banyak worker Gunicorn biasanya lebih cepat dan jauh lebih mudah dipahami.
Cara Kerja Django Async Views di ASGI
WSGI pada dasarnya bersifat sinkron: setiap request yang sedang berjalan menempati satu thread atau proses worker dari awal hingga akhir, sehingga 50 request lambat membutuhkan 50 worker. ASGI menggantikan model itu dengan event loop yang menyelang-nyeling banyak request pada satu worker, menangguhkan sebuah coroutine setiap kali ia meng-await I/O dan melanjutkannya ketika data tiba. Dokumentasi async Django resmi menjelaskan dua adapter yang memungkinkan koeksistensi ini: di ASGI, Django menjalankan view async def secara native pada loop dan mendorong view sinkron ke threadpool dengan sync_to_async; di WSGI, Django membungkus async views dalam async_to_sync dan menjalankannya hingga selesai, membuang setiap manfaat konkurensi.
Konsekuensi praktisnya lugas: view async def yang di-deploy pada server WSGI berperilaku seperti view sinkron yang lebih lambat. Konkurensi hanya terwujud pada server ASGI. Sebuah async view minimal yang memanggil API eksternal tampak nyaris identik dengan padanan sinkronnya, dengan perbedaan yang terpusat pada await.
# views.py
import httpx
from django.http import JsonResponse
async def dashboard(request):
# Di ASGI, coroutine ini berjalan pada event loop, sehingga worker
# bebas melayani request lain selagi httpx menunggu perjalanan bolak-balik jaringan.
async with httpx.AsyncClient(timeout=5.0) as client:
response = await client.get("https://api.example.com/metrics")
return JsonResponse(response.json())Keuntungan di sini bukanlah bahwa satu request itu selesai lebih cepat; ia memakan waktu jam-dinding yang sama. Keuntungannya adalah worker tidak terblokir selama await, sehingga throughput di bawah beban konkuren meningkat sementara jumlah proses tetap datar.
Model yang sama membuka pola respons yang canggung di WSGI. Sejak Django 4.2, StreamingHttpResponse menerima async generator, sehingga sebuah view dapat meng-yield potongan data begitu sumber upstream memproduksinya, cocok untuk Server-Sent Events dan aliran token LLM yang diproksikan di mana koneksi tetap terbuka selama beberapa detik. Protokol dua arah yang persisten seperti WebSockets tetap dirutekan melalui Django Channels alih-alih view HTTP biasa, tetapi keduanya bertumpu pada fondasi ASGI yang sama, sehingga proyek yang mengadopsi async views sudah membayar biaya infrastruktur untuk fitur real-time di kemudian hari.
Memilih Server ASGI Django pada 2026
Django menyertakan objek aplikasi ASGI di asgi.py, tetapi ia tidak menjalankan dirinya sendiri; sebuah server ASGI khusus yang menggerakkan event loop. Spesifikasi ASGI mendefinisikan antarmuka yang diimplementasikan setiap server ini, itulah sebabnya mereka dapat dipertukarkan pada level protokol dan berbeda terutama dalam performa serta cakupan protokol.
| Server | Diimplementasikan dalam | Paling cocok untuk | |--------|----------------|----------| | Uvicorn | Python (uvloop) | ASGI umum, HTTP/1.1, default yang lazim | | Daphne | Python | Django Channels, WebSockets, HTTP/2 | | Granian | Rust | Throughput mentah tertinggi, HTTP/1 dan HTTP/2 | | Hypercorn | Python | HTTP/2 dan HTTP/3 (QUIC) |
Untuk sebagian besar deployment 2026, Uvicorn yang dijalankan sebagai worker class Gunicorn tetap menjadi pilihan yang andal: Gunicorn mengawasi siklus hidup proses, me-restart worker yang crash, dan menangani sinyal, sementara Uvicorn menggerakkan event loop di dalam masing-masing worker. Satu detail migrasi kerap menyandung proses upgrade: worker class Gunicorn dipindahkan keluar dari inti Uvicorn ke paket uvicorn-worker terpisah sejak Uvicorn 0.30, sehingga jalur import-nya berubah.
# Instal paket worker terlebih dahulu: pip install uvicorn-worker
gunicorn myproject.asgi:application \
--workers 4 \
--worker-class uvicorn_worker.UvicornWorker \
--bind 0.0.0.0:8000Tim yang mengejar throughput maksimum semakin banyak beralih ke Granian, server berbasis Rust yang menghilangkan overhead parsing HTTP di sisi Python. Apa pun pilihannya, kisah deployment inilah alasan async hanya muncul di produksi ketika dikonfigurasi secara sengaja; penyiapan spesifik ASGI mencerminkan kehati-hatian operasional yang dibahas dalam modul pertanyaan wawancara deployment Django.
ORM Async dan Jebakan SynchronousOnlyOperation
Django 4.1 menambahkan metode query asinkron di seluruh ORM: aget, acreate, asave, adelete, acount, aexists, aaggregate, serta iterasi dengan async for. Metode-metode ini menyediakan permukaan yang ramah-async, tetapi satu peringatan penting bertahan hingga 2026: lapisan database di bawahnya tidak asinkron secara native. Bahkan dengan psycopg3, Django mengeksekusi query di dalam threadpool dan mengeksposnya melalui pembungkus async, sehingga ORM async memperbaiki ergonomi dan menghindari pemblokiran loop tanpa benar-benar menghadirkan I/O database async menyeluruh dari ujung ke ujung.
Mode kegagalan yang paling umum adalah memanggil metode ORM sinkron secara langsung di dalam async view. Django mendeteksi konteks async dan menolaknya, memunculkan SynchronousOnlyOperation untuk mencegah panggilan yang memblokir membekukan event loop bagi setiap request lain yang berbagi worker tersebut.
Exception ini adalah pengaman, bukan bug. Menjangkau DJANGO_ALLOW_ASYNC_UNSAFE=true untuk membungkamnya justru memperkenalkan kembali persis perilaku pemblokiran yang seharusnya dihilangkan async. Perbaikan yang benar adalah metode ORM async (aget alih-alih get) atau pembungkus sync_to_async eksplisit di sekitar kode yang tidak memiliki padanan async.
Async views terbaca rapi begitu metode query async menggantikan kembarannya yang sinkron. Pola di bawah menghitung baris dan mengalirkan sepuluh record pertama tanpa pernah meninggalkan event loop.
# views.py
from django.http import JsonResponse
from .models import Article
async def latest_articles(request):
# acount() dan iterasi async adalah pembungkus yang aman-async di sekitar ORM.
count = await Article.objects.acount()
titles = []
async for article in Article.objects.order_by("-created_at")[:10]:
titles.append(article.title)
return JsonResponse({"count": count, "titles": titles})Sebagian kode tidak memiliki padanan async: SDK pihak ketiga yang hanya menawarkan panggilan sinkron, atau rantai penelusuran ORM yang padat dan tidak sepadan untuk ditulis ulang. Membungkusnya dengan sync_to_async dari pustaka asgiref memindahkan pekerjaan itu ke sebuah thread dan menjaga loop tetap responsif. Argumen thread_sensitive=True adalah default yang aman karena ia mengarahkan setiap panggilan yang dibungkus ke satu thread executor bersama, mempertahankan status koneksi database dan transaksi yang akan rusak jika panggilan tersebar ke thread yang sembarang.
# views.py
from asgiref.sync import sync_to_async
from .services import build_report # sebuah fungsi sinkron
async def report_view(request):
# thread_sensitive=True menjaga panggilan yang dibungkus tetap pada satu thread bersama,
# mempertahankan status koneksi dan transaksi lintas batas.
report = await sync_to_async(build_report, thread_sensitive=True)(request.user.id)
return JsonResponse(report)Performa Django Async: Kapan Konkurensi Menang
Performa Django async adalah cerita tentang tumpang-tindih I/O, bukan kecepatan mentah. Kemenangan paling jelas datang dari menyebarkan panggilan jaringan independen dengan asyncio.gather: tiga request eksternal masing-masing 200ms menghabiskan sekitar 600ms secara berurutan tetapi selesai dalam sekitar 200ms secara konkuren, karena await-nya saling tumpang-tindih pada loop yang sama.
# views.py
import asyncio
import httpx
from django.http import JsonResponse
async def aggregate(request):
async with httpx.AsyncClient(timeout=5.0) as client:
# Tiga panggilan independen berjalan konkuren alih-alih satu demi satu.
weather, prices, news = await asyncio.gather(
client.get("https://api.example.com/weather"),
client.get("https://api.example.com/prices"),
client.get("https://api.example.com/news"),
)
return JsonResponse({
"weather": weather.json(),
"prices": prices.json(),
"news": news.json(),
})Kasus sebaliknya sama pentingnya. Sebuah view yang menjalankan satu query lokal cepat tidak memperoleh apa pun dari async dan sering justru merugi, karena kini setiap request membayar penjadwalan event-loop ditambah lompatan threadpool ke driver database sinkron. Async juga membebankan pajak yang lebih halus di setiap batas sync/async: mencampur middleware sinkron dan asinkron memaksa Django beralih antara loop dan sebuah thread pada setiap transisi, dan sebuah request yang melintasi garis itu beberapa kali per respons mengakumulasi latensi nyata. Menjaga stack middleware seragam async, atau seragam sync, menghilangkan peralihan tersebut.
Keputusannya menyempit ke bentuk beban kerja alih-alih preferensi terhadap sintaks modern.
| Beban kerja | Default yang lebih baik |
|----------|----------------|
| Banyak panggilan API eksternal lambat per request | Async view dengan asyncio.gather |
| Streaming berdurasi panjang atau Server-Sent Events | Async view dengan async generator |
| Satu query database cepat, ringan-CPU | Sync view, lebih banyak worker Gunicorn |
| Rendering atau komputasi CPU-bound | Sync view, alihkan ke task queue |
Untuk pekerjaan yang benar-benar berjalan lama, async views sama sekali bukan alat yang tepat; menahan sebuah request tetap terbuka untuk mengerjakan pekerjaan selama bermenit-menit memboroskan koneksi, terlepas dari model konkurensinya. Pekerjaan semacam itu tempatnya di background worker, sebuah tradeoff yang dieksplorasi dalam panduan tentang task async Celery di Django.
Adopsi seharusnya mengikuti pengukuran alih-alih intuisi. Cara yang jujur untuk membenarkan async adalah dengan load-test endpoint spesifik itu menggunakan alat seperti Locust atau k6 pada konkurensi realistis, membandingkan versi sinkron pada N worker terhadap versi async pada perangkat keras yang sama. Endpoint yang didominasi oleh satu panggilan eksternal dengan latensi tinggi menunjukkan jurang lebar yang menguntungkan async; endpoint yang didominasi oleh query cepat kerap menunjukkan async sedikit tertinggal begitu lompatan threadpool ikut diperhitungkan. Memprofil request terlebih dahulu juga mengungkap apakah bottleneck-nya memang I/O, sebab async tidak berbuat apa-apa untuk view yang lambat akibat query tanpa indeks, sebuah masalah yang dibahas dalam pembahasan tentang mengoptimalkan query Django ORM.
Siap menguasai wawancara Django Anda?
Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.
Pertanyaan Wawancara Django Async untuk 2026
Wawancara Django async menyelidiki apakah seorang kandidat memahami modelnya atau sekadar mengenali kata kuncinya. Pertanyaan-pertanyaan di bawah mencerminkan apa yang benar-benar ditanyakan wawancara senior pada 2026, masing-masing disertai jawaban yang diberikan seorang engineer berpengalaman.
Apa yang berubah ketika sebuah async view berjalan di WSGI alih-alih ASGI? Di WSGI, Django membungkus coroutine dalam async_to_sync dan menjalankannya hingga selesai pada thread request, sehingga ia berperilaku seperti view sinkron yang lebih lambat tanpa manfaat konkurensi sama sekali. Hanya server ASGI yang menjalankan event loop yang memungkinkan worker melayani request lain selama sebuah await.
Mengapa Article.objects.get(pk=1) memunculkan SynchronousOnlyOperation di dalam async view? Panggilan ORM sinkron akan memblokir event loop, menghambat setiap request lain pada worker itu. Django mendeteksi konteks async dan menolaknya. Perbaikannya adalah metode async await Article.objects.aget(pk=1), atau sync_to_async untuk kode yang tidak memiliki padanan async.
Apakah ORM async Django benar-benar non-blocking? Tidak. Metode async adalah pembungkus yang ergonomis; query yang mendasarinya tetap berjalan di dalam threadpool karena driver database belum terintegrasi untuk eksekusi async native secara menyeluruh. Manfaatnya adalah menjaga loop tetap bebas, bukan I/O database paralel pada level driver.
Kapan async views sebaiknya dipilih ketimbang task queue seperti Celery? Async views cocok untuk konkurensi I/O bercakupan-request yang harus selesai sebelum respons, seperti mengagregasi beberapa API. Pekerjaan yang berumur lebih panjang dari request, membutuhkan retry, atau berjalan bermenit-menit tempatnya di Celery atau background tasks Django, sebab menahan koneksi HTTP tetap terbuka untuknya memboroskan sumber daya server.
Berapa biaya mencampur middleware sync dan async? Setiap transisi antara komponen sync dan async memaksa Django melompat antara event loop dan sebuah thread melalui sync_to_async atau async_to_sync. Sebuah request yang melintasi batas itu berulang kali membayar overhead kumulatif, sehingga stack middleware yang seragam berkinerja lebih baik daripada yang berselang-seling.
Kesimpulan
- Async views hanya memberikan konkurensi pada server ASGI; view yang sama di WSGI berjalan sinkron melalui
async_to_sync. - Deploy Uvicorn via paket
uvicorn-workerdi bawah Gunicorn, atau Granian untuk throughput maksimum, dan perlakukan penyiapan ASGI sebagai langkah deployment yang eksplisit. - Gunakan async views ketika sebuah request menunggu banyak panggilan I/O eksternal yang lambat; pertahankan endpoint query-cepat dan CPU-bound tetap sinkron dengan lebih banyak worker.
- Gunakan
aget,acreate, danasync fordi dalam async views, dan ingat bahwa ORM tetap menjalankan query di dalam threadpool alih-alih async secara native. - Perlakukan
SynchronousOnlyOperationsebagai pengaman: perbaiki dengan metode async atausync_to_async(thread_sensitive=True), jangan pernah dengan menonaktifkan pemeriksaan itu. - Jaga stack middleware seragam sync atau async untuk menghindari pembayaran penalti peralihan-thread pada setiap perlintasan batas.
Mulai berlatih!
Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.
Tag
Bagikan
Artikel terkait

Django dan Celery: Pemrosesan Tugas Asinkron dan Pertanyaan Wawancara 2026
Panduan lengkap Django Celery dengan contoh kode praktis, task routing, penjadwalan Celery Beat, konfigurasi produksi, dan pertanyaan wawancara teknis 2026.

Mendalami Serializer Django REST Framework: Validasi, Nested, dan Optimasi N+1
Panduan lengkap menguasai DRF serializers: pipeline validasi, nested serializers, penanganan relasi kompleks, dan teknik optimasi untuk menghindari N+1 queries.

Django dan PostgreSQL pada 2026: Pengindeksan, Pencarian Teks Lengkap, dan Pertanyaan Wawancara
Panduan praktis optimasi Django PostgreSQL: indeks B-tree, parsial, dan penutup, pencarian teks lengkap dengan SearchVector dan GIN, plus pertanyaan wawancara 2026.