I haven't tried Async Django, (But use normal Django on a few work and hobby project) and am hesitant based on my experience in rust, and not finding a fault I think coloring my Python/Django code would be advantageous to do.
Four releases later async will be marketed as "this has been a mistake" and the green threads will be the best thing ever. Thousands of blog posts will be written and everyone has to rewrite their code bases. Repeat for goroutines etc.
Async functions allow me to build massively parallel and concurrent systems with ease - it's beautiful.
In comparison, I'm not as fond of Go's approach to concurrency, which feels less elegant to me.
But there is a big downside, that's true.
python users only have themselves to blame for ignoring it.
> IIRC the history of the async things in TLA in order: Twisted (callbacks), Eventlet (for Second Life by Linden Labs), tornado, gevent; gunicorn, Python 3.5+ asyncio, [uvicorn,]
Async/await > History: https://en.wikipedia.org/wiki/Async/await
However, if we are to be honest, the history of async usage in Django wasn't very impressive. You could argue that for most products, you don’t really need async. It was just an extra layer of complexity without any significant practical benefit.
Over the last couple of years, AI use-cases have changed that perception. Many AI products have calling external APIs over the network as their bottleneck. This makes the complexity from async Python worth considering. FastAPI with its intuitive async usage and simplicity have risen to be the default API/web layer for AI projects.
I wrote about using async Django in a relatively complex AI open source project here: https://jonathanadly.com/is-async-django-ready-for-prime-tim...
tldr: Async django is ready! there is a couple of gotcha's here and there, but there should be no performance loss when using async Django instead of FastAPI for the same tasks. Django's built-in features greatly simplify and enhance the developer experience.
So - go ahead and use async Django in your next project. It should be a lot smoother that it was a year or even six months ago.
Can you expand more on why these AI cases make the complexity tradeoff different?
I'd imagine think waiting on a 3rd party LLM API call would be computationally very inexpensive compared to what's going on at the business end of that API call. Further lowering the cost, Django is usually configured to use multiple threads and/or processes so that this blocking call won't keep a CPU idle, no?
They’re very slow. Like, several seconds to get a response slow. If you’re serving a very large number of very fast requests, you can argue that the simplicity of the sync model makes it worth it to just scale up the number of processes required to serve that many requests, but the LLM calls are slow enough that it means you need to dramatically scale up the number of serving processes available if you’re going to keep the sync model, and that’s mostly to have CPUs sitting around idle waiting for the LLM to come back. The async model can also let you parallelize calls to the LLMs if you’re making multiple independent calls within the same request - this can cut multiple seconds off your response time.
If the alternative to Async is more processes, rather than threads, a clear benefit is reduced memory usage and reduced process startup time.
Not necessarily true. Many process-parallel Python environments support using fork(2) for parallelism (multiprocessing, gunicorn, celery).
For similar processes (e.g. parallel waiting on RPCs) that removes the memory overhead. It also largely mitigates startup time costs (especially if forks are reused for multiple requests, which they are in most forking contexts).
While there is debate and grumbling in the Python community about fork(2)’s rough edges re: signals/threads/MacOS, these issues are usually handled inside parallelism-management library code and rarely concern application level developers.
To restate my comment: I argued (1) this CPU cost would be very marginal compared to the LLM API compute cost, and (2) the CPU blocking claim doesn't really hold, due to the wonders of threads and processes.
People who like synchronous Python can use Django.
People who like asynch Python can use Starlette - the async web server also written by the guy who wrote Django.
It’s not clear why Django needs to be async, especially when I get the sense there’s developers who like async and developers who prefer synch. It’s a natural fit for Django to fulfill the sync demand and Starlette to fulfill the async. They’re both good.
Django has a batteries-includes approach, benefits from tighter integration of orm, auth, form handling, etc, and has a huge 3rd party ecosystem.
First-class async support in Django allows Django users to avoid jumping through hoops (celery, channels, ...) for longer-running requests, something especially noticable if you're calling any kind of AI service.
Which is a very Django way to think: lots of tools ready to go, use only what you need.
Django is fine for writing a thin CRUD layer around a database. It makes the easy stuff easy. But doesn't seem to help much for the hard stuff and often actively hinders it.
Really the main reason for Django is its ORM and migrations. It's basically the other Python ORM (next to SQLAlchemy) but, unlike SQLAlchemy, it's not designed to be used standalone. In my experience I find Django (and active record ORMs in general) easier for people to get started with, but massively limiting in long run for complex domains.
This assumes that people don't do multi-page apps or sites any more, which ... isn't true. And I believe django-ninja replaces forms/serialization/deserialization and routing, while nicely integrating with everything else.
> Django is fine for writing a thin CRUD layer around a database.
In my dozen or so years with Django, I confess I did more than a few thin CRUD layers around a database. But also worked on billing systems for telecoms, insurance provider API services, live/on demand audio/video streaming services, a bunch of business process apps, AI codegen tools, and other web apps and API backends that were way more than thin CRUD layers around databases.
Django was rarely a hindrance. In fact, Python being sync-only (or Django not supporting async) was usually more of a hindrance that anything Django specific.
> In my experience I find Django (and active record ORMs in general) easier for people to get started with, but massively limiting in long run for complex domains.
In my exprience the only situations where Django's ORM doesn't help much is when you have a lot of business logic in your database (views, stored procedures), or the database is organized in a way that's not Django's preffered way. Still works, mind you, just not as great a experience. However, the vast majority of projects I've encountered have none of those.
Otherwise, I've found its ORM quite powerful, and easy to drop down to raw() in cases where you really need it (which was maybe 1% on the projects I've worked).
Django having async support means you can use the Django ORM, and the Django request/response cycle, and generally not need to write your async and your sync web code using slightly different APIs.