Using sync and async code together¶
Writing sync code is easy, fun, and readable. Writing async code is sometimes required:
If you use HTTP requests to other services
If you are using SSE or WebSockets
etc
But, how can one use the best of two worlds?
Running everything under ASGI¶
Django provides default asgi interface to run both async and sync views.
But, Django has to run a threadpool, emulate async mode for sync views, and switch contexts.
This will come with a small performance penalty.
The same is true for sync / async middleware.
See:
https://docs.djangoproject.com/en/stable/howto/deployment/asgi/uvicorn/
https://docs.djangoproject.com/en/stable/topics/async/#performance
This is supported in django-modern-rest.
Separating sync from async¶
Another way is to run two instances of your app:
One with
gunicornand sync-only views and middlewareThe second one with
uvicornand async-only views and middleware
django-modern-rest does not allow mixing async
and sync endpoints in one controller just for this reason.
How to properly isolate these two applications?
Create two files for urls:
urls.pyfor default sync mode andasync_urls.pyfor async mode. Make sure that async urls have a unique URL prefix:/async/Create two settings file (we recommend using django-split-settings for that
In these two settings file specify two different ROOT_URLCONF’s, one for
urls.pyand one forasync_urls.pyRun two different instances of Django: one with
gunicornandurls.py, one withuvicornandasync_urls.pyIn your proxy server route
/async/url prefix touvicornand all others togunicorn
Done.
Now async views with work in async runtime, while sync views will work in sync runtime with minimal overhead.
This is supported in django-modern-rest.