7 октября 2026 г.

FastAPI Production Checklist

Что проверить перед выкладкой FastAPI в прод.

Запустить FastAPI локально — легко. Запустить его в продакшене так, чтобы он не падал, не тормозил и не терял данные — это отдельная работа. Ниже — чек-лист, который я использую перед каждым релизом. Он не претендует на истину в последней инстанции, но покрывает 90% проблем, с которыми я сталкивался.

Наблюдаемость

Без наблюдаемости вы не знаете, что происходит с приложением. Логи, метрики, трейсы — три столпа.

Логи

Что важно:

  • Структурированные логи (JSON), а не print().
  • Уровни: DEBUG, INFO, WARNING, ERROR, CRITICAL.
  • Correlation ID — чтобы связать логи одного запроса.
  • Ротация — чтобы не забили диск.

Пример с structlog:

import structlog

logger = structlog.get_logger()

@app.get("/users/{user_id}")
async def get_user(user_id: int):
    logger.info("fetching_user", user_id=user_id)
    user = await db.get(User, user_id)
    if not user:
        logger.warning("user_not_found", user_id=user_id)
        raise HTTPException(404)
    return user

Безопасность

Безопасность — не опция и не «потом добавим». Даже пет-проект могут взломать, а портфолио — тем более. Ниже — три вещи, которые закрывают 80% проблем: CORS, rate limiting, JWT.

CORS

Что это. Механизм, который говорит браузеру, с каких доменов можно обращаться к твоему API. Если настроить неправильно — либо всё открыто, либо всё сломано.

Что важно:

  • Разрешать только свои домены.
  • Не использовать allow_origins=["*"] в продакшене.
  • Ограничить методы и заголовки.
  • Не сочетать allow_origins=["*"] с allow_credentials=True — это несовместимо.

Пример:

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://mydomain.com", "https://www.mydomain.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
)

Rate Limiting

Что это. Ограничение количества запросов с одного IP или от одного пользователя. Защищает от брутфорса, спама и DDoS.

Что важно:

  • Разные лимиты для разных эндпоинтов.
  • Лимит на IP и на пользователя.
  • Хранить счётчики в Redis, а не в памяти.
  • Отдавать 429 Too Many Requests с заголовком Retry-After.

Пример с slowapi:

from slowapi import Limiter
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter

@app.get("/login")
@limiter.limit("5/minute")
async def login(request: Request):
    ...

Что лимитировать:

  • Логин — 5/мин.
  • Регистрация — 3/час.
  • API — 100/мин.
  • Тяжёлые запросы — 10/мин.
  • Пароль-ресет — 3/час.

База данных

База — сердце приложения. Если она упадёт или потеряет данные, всё остальное уже не важно. Ниже — два столпа: миграции и бэкапы. Плюс немного про пул соединений и индексы, потому что без них база тормозит.

Миграции Alembic

Что это. Alembic — инструмент для управления изменениями схемы БД. Каждое изменение — отдельная миграция, которую можно применить или откатить.

Что важно:

  • Все изменения схемы — только через миграции.
  • Не менять БД вручную.
  • Проверять миграции на тестовой БД.
  • Хранить миграции в git.
  • Писать downgrade, а не только upgrade.
  • Не редактировать применённые миграции.

Пример:

# Создать миграцию
alembic revision --autogenerate -m "add users table"

# Применить все миграции
alembic upgrade head

# Применить одну
alembic upgrade +1

# Откатить одну
alembic downgrade -1

# Откатить всё
alembic downgrade base

# Посмотреть текущую версию
alembic current

# Посмотреть историю
alembic history

Пример миграции:

"""add users table

Revision ID: abc123
Revises:
Create Date: 2026-01-01 12:00:00
"""
from alembic import op
import sqlalchemy as sa

def upgrade():
    op.create_table(
        "users",
        sa.Column("id", sa.Integer, primary_key=True),
        sa.Column("email", sa.String(255), unique=True, nullable=False),
        sa.Column("created_at", sa.DateTime, server_default=sa.func.now()),
    )
    op.create_index("ix_users_email", "users", ["email"])

def downgrade():
    op.drop_index("ix_users_email", table_name="users")
    op.drop_table("users")

Бэкапы (Резервные копии)

Что это. Регулярные копии БД, которые позволяют восстановиться после сбоя, ошибки или атаки.

Что важно:

  • Ежедневно.
  • В разные места (S3, другой сервер).
  • Проверять восстановление.
  • Шифровать.
  • Хранить минимум 30 дней.
  • Автоматизировать.

Примери скрипта для резервого копирования:

#!/bin/bash
# backup.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="backup_${DATE}.sql.gz"

# Создать бэкап
pg_dump -U user -h localhost dbname | gzip > /backups/${BACKUP_FILE}

# Загрузить в S3
aws s3 cp /backups/${BACKUP_FILE} s3://my-backups/

# Удалить старые (старше 30 дней)
find /backups -name "backup_*.sql.gz" -mtime +30 -delete

Похожие посты