[Django]-Django 3.x – which ASGI server (Uvicorn vs. Daphne)

40👍

Simple Answer:
Since you’ve used gunicorn before and you’re familiar with it, go with uvicorn, specially since it should be used as a gunicorn worker in production.
If you have no experience with it, then I would suggest daphne.
Both will do the job on a simple project, and the performance seems to be equal.


Explanation:

ASGI is a rather new technology, and so is python’s async/await in comparison to most other design-changing elements in the language.
Both uvicorn, daphne and hypercorn are also in active development, so there can’t be any "fair" benchmarking of these libraries. So when it comes to choosing what you want, you mostly have to take their word for it when they say for example; they aim for being fast, simple to use, lightweight or whatever.

All that being said, I can still share my experience with Uvicorn and Daphne:

Daphne is definitely the bulkier project, it has a lot of dependencies that are not entirely used in every project. They sure have done their best covering lots of features, and since they are also part of the Django team, you should expect a better long term compatibility with Django. Getting started with Daphne can be intimidating though.

Uvicorn is the light-weight one, you can even read the code of the whole library and kinda understand how the cogs turn inside. Since I’ve mostly used Uvicorn, I know it has some missing features and bugs that are rather expected to work out of the box, If you want a custom behavior from your ASGI server, tampering with Uvicorn is easier than the alternative. My favorite part about Uvicorn, is that it is not even a process manager, and is designed to work as gunicorn’s worker for production.

Side note: hooking into Uvicorn is not actually intended or easy.
It’s not generally good practice to do this, but given that after 18 hours of searching for an alternative (I personally wanted to catch and handle SIGTERM for graceful shutdown, but the normal methods didn’t work since everything is in a async loop), I couldn’t find any better ways. So I will shamelessly put a piece of code that will grant you the elusive "server" instance. From there, thread carefully. (no pun intended)

import inspect #Might not be future proof! Use with care
from uvicorn import Server as UvicornServer
server = next( server for frameinf in inspect.stack() if 'server' in frameinf[0].f_locals and isinstance(server:=frameinf[0].f_locals['server'], UvicornServer) )

Another Sidenote:
If you actually choose to go with Uvicorn, and you’re using django with channels, you might want to remove "daphne" first, since it’s a rather unused dependency of channels.

Leave a comment