FastAPI закрепился как один из самых быстрых способов выпустить рабочее API на Python — не только по скорости выполнения запросов за счёт асинхронности, но и по скорости самой разработки: типизация через Pydantic и автогенерация документации убирают значительную часть рутины, которая раньше писалась вручную в Flask или Django REST Framework.
Установка и запуск занимают минуты:
pip install fastapi uvicorn
from fastapi import FastAPI app = FastAPI() @app.get("/status") def status(): return {"ok": True}
uvicorn main:app --reload
После запуска эндпоинт уже доступен, а на /docs автоматически появляется интерактивная Swagger-документация — без единой строчки кода, написанной специально для неё.
Вместо ручной проверки типов и обязательных полей в теле каждого запроса, FastAPI использует Pydantic-модели, которые валидируют данные автоматически до того, как они попадут в тело функции:
from pydantic import BaseModel class OrderRequest(BaseModel): email: str area: float complexity: str = "base" @app.post("/calc") def calc(order: OrderRequest): rate = 1500 if order.complexity == "premium" else 900 return {"price": round(order.area * rate)}
Если клиент пришлёт запрос без обязательного поля email или с area, которое не приводится к числу, FastAPI сам вернёт ответ 422 с понятным описанием ошибки — без написания отдельного кода валидации.
Там, где обработчик делает сетевой запрос или обращение к базе данных, асинхронное определение функции через async def позволяет серверу обслуживать другие запросы, пока идёт ожидание ответа, вместо блокировки целого воркера:
@app.get("/external") async def external(): async with httpx.AsyncClient() as client: r = await client.get("https://api.example.com/data") return r.json()
Для работы с базой данных в асинхронном стиле используется асинхронный драйвер (например, asyncpg для PostgreSQL через SQLAlchemy в async-режиме) — синхронный ORM-вызов внутри async def сведёт на нет весь выигрыш от асинхронности.
Swagger UI на /docs и альтернативный ReDoc на /redoc генерируются автоматически из тех же Pydantic-моделей и аннотаций типов, которые уже написаны для валидации — документация не может разойтись с реальным кодом API, потому что это один и тот же источник правды, а не отдельно поддерживаемый файл.
Встроенный сервер uvicorn --reload предназначен только для разработки. В продакшне используется связка нескольких воркеров Uvicorn под управлением Gunicorn (gunicorn -k uvicorn.workers.UvicornWorker main:app -w 4) за обратным прокси Nginx, который принимает внешние соединения, обслуживает статику и терминирует SSL, передавая остальные запросы на локальный порт приложения.
FastAPI поставляется с интегрированным тестовым клиентом на основе TestClient, который позволяет писать тесты эндпоинтов без поднятия реального сервера: from fastapi.testclient import TestClient client = TestClient(app) def test_status(): assert client.get("/status").json() == {"ok": True}. Такие тесты запускаются за миллисекунды и проверяют не только бизнес-логику, но и то, что Pydantic-валидация действительно отклоняет некорректные данные — это особенно ценно перед деплоем изменений в продакшн-API, которым пользуются внешние интеграции.
Смешивание синхронных блокирующих вызовов (обычный requests.get вместо асинхронного клиента) внутри async def-обработчиков — убивает весь смысл асинхронности, блокируя event loop на время ожидания ответа. Вторая ошибка — отсутствие отдельных Pydantic-моделей для входных и выходных данных, из-за чего во внешний ответ API случайно попадают внутренние поля (хэши паролей, служебные флаги), которые не должны покидать сервер. Третья — запуск в продакшне через --reload, который следит за изменением файлов на диске и перезапускает процесс — лишняя нагрузка и источник нестабильности, не нужный вне разработки. Четвёртая — отсутствие ограничения размера тела запроса и rate limiting на публичных эндпоинтах: без них один медленный или аномально большой запрос может удерживать воркер дольше обычного, а при целенаправленной нагрузке — исчерпать пул воркеров быстрее, чем успеет сработать любая бизнес-логика.