Preparing for Django 3.0: Async is Coming
Django 3.0 is coming in December, and with it, ASGI support. This is the first step toward fully async Django.
What’s ASGI?
WSGI (Web Server Gateway Interface): Synchronous standard that Django has used since day one.
ASGI (Asynchronous Server Gateway Interface): The async equivalent, supporting WebSockets, HTTP/2, and async views.
# WSGI application
def application(environ, start_response):
...
# ASGI application
async def application(scope, receive, send):
...
What Django 3.0 Actually Delivers
Let’s be clear about scope:
Included:
- ASGI server support (run Django under Daphne, Uvicorn)
- Async-safe ORM (sync ORM works in async context via sync_to_async)
- Async middleware support
Not included (yet):
- Async views
- Async ORM queries
- Async template rendering
Django 3.0 is foundation-laying, not the full async experience.
Running Django on ASGI
Create ASGI Application
# myproject/asgi.py
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_asgi_application()
Run with Uvicorn
pip install uvicorn
uvicorn myproject.asgi:application --host 0.0.0.0 --port 8000
Run with Daphne
pip install daphne
daphne myproject.asgi:application
Async Middleware
Django 3.0 supports async middleware:
class AsyncMiddleware:
async def __call__(self, request):
# Async before processing
await self.async_setup()
response = await self.get_response(request)
# Async after processing
await self.async_cleanup()
return response
Sync middleware still works in ASGI mode (wrapped automatically).
The sync_to_async Bridge
Use async code safely in Django:
from asgiref.sync import sync_to_async
@sync_to_async
def get_user(user_id):
return User.objects.get(id=user_id)
async def my_view(request):
user = await get_user(1)
...
Convert sync functions for use in async context.
Preparing Your Codebase
Check Middleware
Ensure custom middleware handles async:
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# Check if async
if asyncio.iscoroutinefunction(self.get_response):
self._is_async = True
else:
self._is_async = False
async def __acall__(self, request):
# Async path
response = await self.get_response(request)
return response
def __call__(self, request):
# Sync path
response = self.get_response(request)
return response
Update Dependencies
Check if your packages support Django 3.0:
- django-rest-framework
- django-debug-toolbar
- django-cors-headers
- Your ORM extensions
Database Backends
PostgreSQL, MySQL, SQLite supported. Some third-party backends may need updates.
What About Channels?
Django Channels already provides async capabilities:
- WebSockets
- Background tasks
- Real-time features
Django 3.0’s ASGI support is complementary:
- Channels uses ASGI
- Native Django ASGI enables future async features
- You can use both together
The Async Django Roadmap
Based on DEP (Django Enhancement Proposals):
- Django 3.0: ASGI support, async middleware
- Django 3.1: Async views (likely)
- Django 3.2+: Async ORM queries (eventually)
Full async Django will take multiple releases.
When to Use ASGI Now
Use ASGI if:
- You need WebSockets (with Channels)
- You’re building real-time features
- You want to experiment with async middleware
Stick with WSGI if:
- Traditional request/response apps
- All your code is synchronous
- You need maximum compatibility
For most apps, WSGI remains fine.
Testing Async Code
from django.test import TestCase
from asgiref.sync import async_to_sync
class AsyncTests(TestCase):
def test_async_function(self):
result = async_to_sync(my_async_function)()
self.assertEqual(result, expected)
# Or use pytest-asyncio
@pytest.mark.asyncio
async def test_async():
result = await my_async_function()
assert result == expected
Upgrade Checklist
- Update Python: 3.6+ required, 3.8+ recommended
- Update dependencies: Check compatibility
- Test middleware: Ensure async compatibility
- Choose server: Uvicorn, Daphne, or Hypercorn for ASGI
- Add asgi.py: Create the ASGI application file
- Run tests: Full test suite on Django 3.0
Final Thoughts
Django 3.0’s async support is a beginning, not an end. The framework is being carefully retrofitted for the async world.
Don’t rush to async. The performance benefits only matter for specific workloads. Most Django apps are I/O-bound at the database, and the ORM isn’t async yet.
Upgrade to 3.0 for the future. Stay synchronous for now.
The async future is coming. Prepare, but don’t rush.