Короткий ответ
Новые обязательные поля вводят как необязательные с безопасным значением по умолчанию на переходный период, удаление/сужение существующих полей делают поэтапно (сначала отметить как deprecated и логировать использование, затем ограничить только после подтверждённого отсутствия использования), а не вносят breaking-изменение одним релизом.
Как это работает подробнее
Схема валидации — это контракт между клиентом и сервером; любое сужение допустимых значений (новое обязательное поле, более строгий тип, уменьшение допустимого диапазона) потенциально отклоняет ранее валидные запросы существующих клиентов. Безопасная эволюция обычно идёт через расширение (добавление необязательных полей) и постепенное сужение только после того, как подтверждено (например, через логирование/метрики), что все клиенты уже используют новый формат.
Постепенное расширение схемы безопаснее для существующих клиентов, но временно усложняет код (поддержка старого и нового формата одновременно) и создаёт технический долг до завершения миграции. Немедленное ужесточение валидации проще в коде, но рискует массово отклонить легитимный трафик старых клиентов. Критерий выбора — насколько управляемы клиенты (внутренний сервис с единым релизным циклом против внешних независимых интеграторов) и насколько критичен простой для бизнеса.
Пример кода
# Переходный этап: новое поле необязательно с безопасным дефолтом
class OrderIn(BaseModel):
items: list[OrderItem]
currency: str = "USD" # новое поле, раньше не было вовсе - дефолт сохраняет совместимость
# Старое избыточно широкое поле временно оставлено, но логируется его использование
legacy_discount_code: str | None = None
# В коде обработчика: если legacy_discount_code заполнен - залогировать метрику
# "legacy_discount_code_used", чтобы оценить, когда можно будет убрать поле.Что использовать на практике
- Практика. Полезно иметь метрики/логи по фактически приходящим данным (какие поля реально заполнены, какие значения встречаются), чтобы принимать решение об ужесточении валидации на основе данных, а не предположений. Для необратимых изменений (переименование поля, изменение единиц измерения) нужен переходный период с поддержкой обоих вариантов и чёткой датой отключения старого.
Подводные камни
- Риск. Делают валидацию сразу строгой в новом релизе («так правильнее»), не проверив, какой процент реального трафика перестанет проходить валидацию; не договариваются с владельцами клиентов (другие команды/внешние интеграторы) о сроках миграции, из-за чего изменение валидации воспринимается как внезапная поломка продакшена.