# 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. - Published: 2026-07-03 - Updated: 2026-07-07 - Author: SharpSkill - Tags: django, async, asgi, python, performance - Reading time: 10 min --- 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. > **Kapan Async Benar-Benar Membantu** > > 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](https://docs.djangoproject.com/en/5.2/topics/async/) 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`. ```python # 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](https://asgi.readthedocs.io/en/latest/) 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](https://www.uvicorn.org/) 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. ```bash # 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:8000 ``` Tim 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](/technologies/django/interview-questions/django-deployment). ## 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. > **SynchronousOnlyOperation Adalah Fitur** > > 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. ```python # 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](https://github.com/django/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. ```python # 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. ```python # 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](/blog/django/django-celery-async-tasks-interview-2026). 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](/blog/django/django-orm-optimizing-queries). ## 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-worker` di 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`, dan `async for` di dalam async views, dan ingat bahwa ORM tetap menjalankan query di dalam threadpool alih-alih async secara native. - Perlakukan `SynchronousOnlyOperation` sebagai pengaman: perbaiki dengan metode async atau `sync_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. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/id/blog/django/django-async-views-asgi-2026