Async в Django 5: реальное ускорение

Backend
18 мая 2026Время чтения 9 мин

Долгое время Django ассоциировалась с синхронным request-response и WSGI. С релизом ASGI и Django 5.0 мы наконец можем строить настоящие асинхронные сервисы. Но простое включение async def в вьюхах не даст прироста, если архитектура не готова к параллелизму.

Практика показывает: выигрывают команды, которые планомерно переводят стек на ASGI, обновляют драйверы и выстраивают наблюдаемость, а не просто добавляют пару асинхронных эндпоинтов. Ниже - проверенный набор шагов и паттернов.


Когда асинхронность оправдана

  • Высокая задержка между сервисами: внешние API, очереди, БД.
  • Стриминг данных в real-time интерфейсы (websocket, SSE).
  • Интенсивная работа с файлами и хранилищами.
  • Микросервисы с большим количеством параллельных, но коротких I/O операций.

Если bottleneck - CPU-bound операции, лучше выносить их в Celery/HTMX tasks или Rust-сервисы.


Переход на ASGI без боли

  1. Обновите Django до 5.x и включите ASGI_APPLICATION в настройках.
  2. Перейдите на uvicorn или hypercorn и уберите устаревший WSGI уровень.
  3. Замените драйверы: psycopg3 в режиме async, asyncpg, aioredis.
  4. Проверьте middleware: синхронные классы нужно обернуть в sync_to_async или переписать.
  5. Пересоберите пайплайн деплоя и health-check'ов с учётом нового воркера.

Этот план позволяет перевести проект на ASGI итеративно, не ломая существующие синхронные приложения и админку.


Типичная архитектура

Мы комбинируем Django + PostgreSQL + Redis + FastAPI worker. Django отвечает за бизнес-логику и админку, а сильные async-вьюхи закрывают интеграции. Канал связи - Redis Streams, чтобы не мешать синхронному коду. Отдельные воркеры обслуживают websocket/SSE соединения через channels или strawberry.

client → ASGI → Django async view → внешние API → ответ
                                     ↘ task в Celery/FastAPI

Благодаря этому можно обслуживать до 4-5х больше соединений при том же количестве подов.


Паттерны и анти-паттерны

  • Делегируйте тяжелые HTTP вызовы в сервисы-адаптеры с таймаутами и ретраями.
  • Избегайте смешения sync и async ORM-запросов в одном запросе.
  • Контролируйте размер пулов коннектов, чтобы не заблокировать PostgreSQL.
  • Следите за доступом к глобальным объектам: асинхронность обнажает race conditions.

Пример асинхронной вьюхи

from django.http import JsonResponse
from .models import Author

async def author_featured_book(request, author_id: int):
    author = await Author.objects.select_related("profile").aget(id=author_id)
    book = await author.books.filter(is_featured=True).afirst()
    if book is None:
        return JsonResponse({"author": author.name, "book": None}, status=404)

    reviews = [
        {"rating": review.rating, "comment": review.comment}
        async for review in book.reviews.order_by("-rating").aiterator(chunk_size=5)
    ]

    return JsonResponse(
        {
            "author": author.name,
            "book": {
                "title": book.title,
                "published_at": book.published_at,
                "rating": book.rating,
            },
            "top_reviews": reviews,
        }
    )

Здесь мы используем полноценный асинхронный ORM: aget, afirst и aiterator устраняют необходимость в sync_to_async, уменьшая накладные расходы и делая обработку I/O по-настоящему неблокирующей.


Наблюдаемость и тестирование

  • Покройте ключевые эндпоинты pytest-asyncio тестами и используйте httpx.AsyncClient.
  • Подключите OpenTelemetry или Sentry Performance, чтобы отлавливать блокирующие вызовы.
  • Выставьте метрики на события цикла: количество активных тасков, размер очередей.
  • Реплейте боевой трафик через locust или k6, чтобы найти узкие места.

Без телеметрии асинхронная архитектура превращается в чёрный ящик: критично видеть, где запрос «застрял».


Мини-бенчмарк

Конфигурация RPS (p95) Latency
WSGI + gunicorn 480 210 мс
ASGI + uvicorn 4 workers 1820 78 мс
ASGI + uvicorn + asyncpg 2130 65 мс

Результаты из нашего пилота (обработка заказов и интеграции с CRM). Главное - не забыть включить keep-alive и тюнинг воркеров.


Практические советы

  • Поднимайте gunicorn с uvicorn.workers.UvicornWorker, иначе ASGI не заработает.
  • Используйте asyncpg и psycopg3 для БД, чтобы избежать блокировки.
  • Следите за контекстом: не смешивайте синхронные и асинхронные ORM-запросы.
  • Ищите сторонние библиотеки, которые уже поддерживают async, вместо ручных оберток.
  • Внедряйте таймауты и cancelation: asyncio.wait_for спасает от зависших интеграций.

Асинхронная Django требует дисциплины, но окупается, когда API живёт в плотной интеграционной сети.