Nginx для Django и FastAPI: как выбрать схему
Nginx почти одинаково проксирует Django и FastAPI, но сервер приложений, режимы запуска и работа с долгими запросами отличаются. Разбираем схемы для Django 5.x и FastAPI 0.115+ и показываем, где каждая начинает ломаться.

Nginx не превращает Django или FastAPI в быстрый сервис сам по себе: он принимает внешний HTTP-трафик, раздаёт статику и передаёт запросы серверу приложения. Для Django 5.x чаще выбирают WSGI или ASGI в зависимости от характера нагрузки, а FastAPI почти всегда запускают как ASGI-приложение через Uvicorn. Ниже — практическое сравнение схем для Nginx 1.24+, Django 5.x, FastAPI 0.115+ и Uvicorn 0.30+.
Сначала разделите роли Nginx и приложения
Nginx отвечает за внешний вход: TLS, домен, ограничение размера запроса, раздачу файлов и проксирование. Django или FastAPI отвечают за маршруты, авторизацию, бизнес-логику и работу с базой данных.
Обычная схема выглядит так:
Клиент → Nginx → сервер приложения → база данных или внешние сервисы
Nginx не исполняет Python-код и не заменяет Uvicorn, Gunicorn или другой сервер приложений. Если процесс Python остановился, Nginx сможет вернуть только ошибку 502 или отдать заранее подготовленный файл.
Главный критерий выбора — не название фреймворка, а модель выполнения: синхронное WSGI-приложение, асинхронное ASGI-приложение или смесь обычных и долгих запросов.
ASGI — интерфейс между Python-приложением и сервером, рассчитанный не только на обычный HTTP, но и на асинхронные операции, WebSocket и потоковую передачу данных.[1]
Три рабочие схемы
Django через WSGI
Это самый консервативный вариант для Django. Nginx передаёт запросы процессам Gunicorn, а Gunicorn запускает Django через WSGI. Схема подходит для обычных страниц, административной панели, CRUD-операций и API, где каждый запрос быстро обращается к базе и возвращает ответ.
Цена предсказуемости — синхронная модель. Долгий внешний HTTP-запрос или медленная операция в обработчике удерживает worker. Увеличение числа workers помогает до определённого предела, но повышает потребление памяти.
server {
listen 80;
server_name example.com;
location /static/ {
alias /srv/example/staticfiles/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Здесь Nginx отправляет весь динамический трафик на локальный порт 8000. Сам процесс Django должен слушать этот порт через выбранный сервер приложений, а не через встроенный сервер разработки.
Django через ASGI
Django 5.x имеет ASGI-интерфейс. Он нужен, если проект использует асинхронные представления, WebSocket через совместимый стек или много операций, которые можно выполнять асинхронно. Простая замена WSGI на ASGI не ускорит синхронный код и не отменит ограничения синхронных библиотек.
В этой схеме Nginx почти не меняется. Меняется процесс за ним: приложение запускается через ASGI-сервер, например Uvicorn. Точный способ запуска зависит от того, используете ли вы systemd, Docker или другой менеджер процессов.
server {
listen 80;
server_name django.example.com;
location /static/ {
alias /srv/django/staticfiles/;
}
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Не смешивайте ASGI с обещанием «все запросы теперь неблокирующие». Если view вызывает синхронный драйвер базы, файловую систему или сторонний SDK, этот участок всё равно может блокировать worker.
FastAPI через ASGI
FastAPI изначально рассчитан на ASGI. В типичной конфигурации Nginx проксирует запросы в Uvicorn, а Uvicorn запускает приложение и принимает HTTP-соединения. Конфигурация Nginx почти идентична варианту для Django ASGI: различается не прокси, а приложение и его жизненный цикл.
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Для FastAPI важно отдельно проверить долгие ответы, загрузку файлов и WebSocket. Nginx может буферизовать ответ, ограничивать размер тела запроса или закрывать соединение раньше приложения.
Что выбрать в конкретном проекте
| Схема | Когда подходит | Цена решения | Что проверить |
|---|---|---|---|
| Nginx → Gunicorn → Django WSGI | Обычный сайт, админка, синхронный API | Долгие операции занимают worker | Число workers, время ответа, медленные запросы к БД |
| Nginx → Uvicorn → Django ASGI | Асинхронные view, WebSocket, смешанная нагрузка | Синхронный код всё ещё может блокировать выполнение | Совместимость библиотек и реальную долю async-кода |
| Nginx → Uvicorn → FastAPI | API, WebSocket, потоковые и асинхронные операции | Нужно следить за таймаутами и блокирующими вызовами | Размер тела запроса, streaming, фоновые задачи |
Когда достаточно WSGI
Выбирайте Django WSGI, если проект в основном отдаёт HTML, выполняет короткие операции с реляционной базой и не использует WebSocket. Это хороший вариант для команды, которая хочет минимальное количество движущихся частей и уже имеет стабильную WSGI-инфраструктуру.
Когда оправдан ASGI
ASGI имеет смысл, когда асинхронность нужна самому приложению: есть длительные сетевые операции, WebSocket, SSE или много одновременных соединений. Если задача только в том, чтобы обслуживать больше обычных страниц, сначала измерьте SQL-запросы, кэширование и количество workers. Переход на ASGI не исправит N+1-запросы и медленную базу.
Когда выбрать FastAPI вместо Django
FastAPI логичен для отдельного API-сервиса, где важны типизация схем запросов, автоматическая OpenAPI-документация и асинхронные endpoint’ы. Django удобнее, если нужны встроенная админка, сессии, зрелая ORM и готовая структура большого веб-приложения. Nginx не влияет на этот выбор: он одинаково может стоять перед обоими приложениями.
Что ломается чаще всего
- 502 Bad Gateway. Проверьте, слушает ли Python-процесс адрес и порт из
proxy_pass. Если приложение запущено в контейнере, адрес127.0.0.1внутри контейнера Nginx указывает на сам контейнер, а не на соседний сервис. - 404 для статики. Убедитесь, что каталог из
aliasсуществует, содержит собранные файлы и доступен пользователю Nginx. Вaliasважны завершающие слеши. - Неверный HTTPS или редиректы по кругу. Приложение должно получать заголовок
X-Forwarded-Proto, а настройки доверия к прокси — соответствовать вашей версии Django или FastAPI-стека. Не включайте доверие ко всем прокси без необходимости. - WebSocket закрывается сразу. Для него нужны HTTP/1.1 и заголовки Upgrade/Connection. Обычный блок прокси без этих заголовков не гарантирует корректное переключение протокола.
- Запрос обрывается на загрузке или streaming. Проверьте лимит тела запроса и таймауты Nginx. Для потокового endpoint’а настройки буферизации могут отличаться от обычного JSON API.
WebSocket и отдельный location
Если WebSocket действительно используется, выделите его маршрут в отдельный блок и передайте служебные заголовки. Пример ниже рассчитан на маршрут /ws/; имя переменной и блок map размещаются в контексте http, а не внутри server.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name api.example.com;
location /ws/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Если WebSocket нет, не добавляйте этот блок «на будущее»: лишняя конфигурация усложняет диагностику. Для SSE и потоковых HTTP-ответов нужен другой набор настроек, прежде всего проверка буферизации и таймаутов.
Как проверять схему перед продакшеном
Сначала проверьте конфигурацию Nginx командой nginx -t, затем выполните запрос к публичному домену и к локальному порту приложения. Сравните статус, заголовки, размер ответа и время до первого байта. Отдельно протестируйте ошибку приложения: Nginx должен отдавать контролируемый ответ, а не раскрывать стек Python.
- обычный GET и POST с реальным размером данных;
- запрос без обязательной авторизации;
- медленный endpoint и превышение таймаута;
- загрузка файла, если она есть;
- WebSocket или потоковый ответ, если они заявлены в проекте;
- перезапуск процесса приложения во время запроса.
Замеры нагрузки нельзя переносить из чужого проекта. Зафиксируйте версию Nginx, количество workers, объём памяти, тип базы, размер ответа и число одновременных клиентов. Сравнивайте p95 и p99 времени ответа, долю ответов 4xx/5xx, загрузку CPU и число активных соединений.
Что делать дальше
Сначала выберите протокол приложения: WSGI для обычного синхронного Django или ASGI для Django с асинхронными сценариями и для FastAPI. Затем настройте отдельную раздачу статики, проверьте заголовки прокси и измерьте p95 под нагрузкой, близкой к реальной. После этого добавьте TLS, централизованные логи Nginx и приложения, а для долгих endpoint’ов отдельно проверьте таймауты и буферизацию. Инвалидация кэша и настройка фоновых задач — отдельные темы: они не решаются одной конфигурацией Nginx.
Проектная работа: От проблемы до защиты: продукт, этапы, вопросы комиссии
Спросить за 15 ₽Источники: NGINX Documentation: Setting up NGINX as a reverse proxy, Uvicorn documentation: Deployment
Частые вопросы
Нужен ли Nginx перед FastAPI, если Uvicorn уже принимает HTTP?
Можно ли запускать Django через Uvicorn?
Почему Nginx возвращает 502 после запуска приложения?
Нужно ли добавлять настройки WebSocket для обычного FastAPI API?
Что выбрать для Django: WSGI или ASGI?
Какие настройки Nginx важнее всего проверить в продакшене?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.