С Flask 2.7 на FastAPI: что сломалось по дороге
2024 год ушёл на перевод legacy-монолита с Flask + Python 2.7 на FastAPI. Не big bang: сначала новые эндпоинты, потом вырезание старых blueprints.
До и после
| Было | Стало | |
|---|---|---|
| Стек | Монолит, Flask, Py2.7 | FastAPI, Pydantic v2 |
| Контракты | «Договорились в чате» | OpenAPI, codegen для клиентов |
| Деплой | Ручные скрипты | Docker, один образ — несколько воркеров |
| Типизация | Почти нет | Модели запроса/ответа, mypy на CI |
Ошибки, которые я бы не повторял
Слишком ранняя декомпозиция. Разбили монолит на пять микросервисов до того, как стабилизировали границы домена. Месяц ушёл на согласование и дублирование логики. Сейчас бы оставили модульный монолит ещё на полгода.
Транзакционность. В Flask часть операций жила в одном request scope с неявным commit. В FastAPI с async и несколькими репозиториями легко получить «деньги списали, заказ не создали». Ввели явные unit of work и outbox для событий — поздно, но необходимо.
Мониторинг. Старые метрики смотрели на процесс gunicorn целиком. После нарезки сервисов пришлось заново поднять RED-метрики, trace_id в заголовках и дашборды по каждому деплою. Первые недели после cutover слепые зоны ловили только по жалобам пользователей.
Что окупилось
- Валидация на входе — меньше 500 из-за «кривого JSON».
- Автодокументация — фронт и QA перестали спрашивать «а какие поля обязательные».
- Docker — одинаковое окружение от ноутбука до прода.
Итог
Миграция языка и фреймворка — это не замена синтаксиса. Это пересборка границ, наблюдаемости и привычек команды. FastAPI сам по себе проблем не решает; он делает правильные решения дешевле, если ты уже знаешь, где границы сервиса.