Soporte Asíncrono en Django: cuándo usarlo, cómo funciona y cuándo NO conviene
- 👤 Andrés Cruz
Django siempre ha sido sinónimo de productividad: ORM potente, admin listo para producción y un ecosistema maduro. Sin embargo, durante años arrastró una fama difícil de ignorar: no destacar por rendimiento. Gran parte de esa percepción viene de su modelo síncrono por defecto.
Desde Django 3.x, el framework incorporó soporte asíncrono, y con ello surgió una pregunta muy habitual:
¿realmente vale la pena usar async en Django?
La respuesta corta es: depende del tipo de carga.
La respuesta larga es justo lo que vas a leer aquí.
¿Qué es el soporte asíncrono en Django?
El soporte asíncrono en Django permite definir vistas asíncronas (async def) y ejecutar toda la cadena de petición en modo asíncrono cuando la aplicación se despliega sobre ASGI (Asynchronous Server Gateway Interface).
En términos simples:
- Django puede no bloquear el servidor mientras espera operaciones de E/S.
- Un mismo worker puede atender muchas solicitudes concurrentes.
- Es especialmente útil para llamadas a APIs externas, streaming, long-polling o bases de datos lentas.
Algo importante que suele pasar desapercibido:
Las vistas async también funcionan bajo WSGI, pero sin beneficios reales de rendimiento y con penalizaciones adicionales.
Django Sync vs Async: diferencias clave que importan de verdad
Modelo síncrono: cómo funciona y por qué limita el rendimiento
En el modelo tradicional (Sync):
- Un worker → una petición a la vez.
- Si la petición espera E/S (base de datos, red, disco), el worker queda bloqueado.
- Para escalar, se agregan más threads o procesos… con más consumo de memoria.
En la práctica, esto hace que Django sufra especialmente cuando:
- Hay latencia de red.
- Se hacen muchas consultas a la base de datos.
- Se depende de servicios externos.
Esto fue evidente al analizar endpoints que simplemente “esperaban” a la base de datos: el servidor estaba ocioso, pero no podía atender nuevas solicitudes.
Modelo asíncrono: multitarea colaborativa y concurrencia real
Con Async, el modelo cambia:
- Un worker puede manejar muchas solicitudes al mismo tiempo.
- Cuando una tarea llega a un
await, libera el control. - Otras solicitudes avanzan mientras tanto.
Este enfoque se conoce como multitarea colaborativa y es mucho más eficiente que el cambio de contexto tradicional entre threads.
Eso sí: async no acelera el código por sí mismo.
Lo que hace es aprovechar mejor el tiempo muerto de E/S.
ASGI vs WSGI en Django: por qué el servidor importa
Qué ocurre si usas async bajo WSGI
Cuando ejecutas una vista async bajo WSGI:
- Django crea un event loop “de emergencia”.
- Puedes usar
await, pero… - Cada request sigue usando un thread.
Resultado:
- ✔ Funciona
- ❌ No escala
- ❌ No obtienes concurrencia real
Por qué ASGI desbloquea el verdadero rendimiento asíncrono
Para obtener beneficios reales necesitas:
- ASGI
- Un servidor como Uvicorn, Daphne o Hypercorn
- Middleware compatible con async
Se puede usar en:
- Cientos de conexiones concurrentes
- WebSockets
- Streaming lento
- Long-polling
Pero ojo: un solo middleware síncrono obliga a Django a volver al modelo basado en threads, anulando gran parte de la ganancia.
Vistas asíncronas en Django: cómo se implementan
Vistas async con async def
Crear una vista asíncrona es trivial:
from django.http import JsonResponse async def mi_vista(request): return JsonResponse({"mensaje": "Hola desde async"}) Para operaciones de E/S, puedes usar librerías async-native como httpx, aiofiles, etc.
Clases, middleware y compatibilidad
En vistas basadas en clases:
- Los métodos HTTP (
get,post) pueden serasync def. __init__yas_view()siguen siendo síncronos.
Si necesitas usar partes de Django que aún son sync (como parte del ORM), debes usar:
from asgiref.sync import sync_to_async resultado = await sync_to_async(funcion_sync, thread_sensitive=True)()Rendimiento real: qué pasa en cargas CPU-bound vs IO-bound
Por qué async rinde peor en tareas de CPU
En pruebas de carga con rutas CPU-bound:
- Async mostró un comportamiento menos predecible.
- Sync tuvo mayor estabilidad y más éxitos totales.
- El event loop no puede paralelizar CPU intensiva.
Para cargas CPU-bound, Sync sigue siendo la mejor opción.
Por qué async multiplica el rendimiento en IO y alta latencia
En rutas IO-bound (lectura y escritura en base de datos):
- Con latencia de 200 ms, async fue:
- ~40× mejor en lecturas
- ~230× mejor en escrituras
- Sync se degradó rápidamente porque los workers quedaban esperando.
Esto confirma algo clave que aprendí probando:
la latencia es el peor enemigo del modelo síncrono.
Async, en cambio, aprovecha ese tiempo muerto.
Limitaciones actuales del soporte asíncrono en Django
El estado real del ORM asíncrono
El ORM async aún está en evolución:
- No todo es 100% asíncrono.
- Algunas operaciones siguen siendo sync internamente.
- Hay que mezclar
awaitconsync_to_async.
Funciona, pero requiere criterio.
Middleware síncrono y otros cuellos de botella
Otros puntos críticos:
- Límite de conexiones a la base de datos (Postgres fue un factor clave).
- Middleware no compatible con async.
- Complejidad adicional en debugging.
Async no simplifica, optimiza.
¿Deberías usar soporte asíncrono en Django en tu proyecto?
Casos donde async sí tiene sentido
- APIs que consumen otras APIs
- Operaciones con alta latencia
- Streaming o WebSockets
- IO intensivo (DB, red, colas)
- Servicios con alta concurrencia
Casos donde sync sigue siendo la mejor opción
- Procesamiento pesado de CPU
- Lógica simple y baja concurrencia
- Apps pequeñas donde la complejidad no se justifica
Buenas prácticas para usar async en Django sin romper tu app
- Usa async solo donde aporta valor
- Mide antes y después
- Evita mezclar middleware sync innecesario
- Controla conexiones a la base de datos
- No reemplaza a Celery: se complementan
Conclusión
El soporte asíncrono en Django no es una bala de plata, pero bien usado puede transformar por completo el rendimiento de una aplicación.
La regla práctica que me dejó la experimentación es simple:
CPU-bound → Sync
IO-bound → Async
Si entiendes esa diferencia y eliges bien, Django sigue siendo una opción extremadamente sólida incluso en escenarios de alta concurrencia.
FAQs rápidas
- ¿Django es realmente asíncrono?
- Sí, bajo ASGI y sin middleware síncrono.
- ¿Necesito reescribir toda mi app en async?
- No. Puedes mezclar vistas sync y async.
- ¿Async reemplaza a Celery?
- No. Async maneja concurrencia; Celery tareas en segundo plano.
Acepto recibir anuncios de interes sobre este Blog.
Descubre cuándo usar el soporte asíncrono en Django, diferencias entre Sync y Async, ASGI vs WSGI y cómo mejorar el rendimiento real de tu app.