Production-oriented Python backend project demonstrating event-driven architecture, Redis cache-aside, PostgreSQL persistence, MongoDB raw event storage, RedPanda/Kafka consumers, Docker Compose, GitHub Actions CI and basic Kubernetes deployment manifests.
Первая версия намеренно не содержит LLM/AI-функций. Фокус проекта: Python backend, event-driven architecture, базы данных, кеширование, контейнеризация, CI/CD и основы Kubernetes.
HTTP
+--------+
| client |
+---+----+
|
v
+---------------+
| order-api |
| FastAPI |
+---+-------+---+
| |
source | | domain events
of truth v v
+------------+ +----------------+
| PostgreSQL | | RedPanda/Kafka |
+------------+ | order.events |
^ +---+--------+---+
| | |
| v v
+------+-----+ +-------------+ +------------------+
| Redis | | order-worker| | analytics-worker |
| cache only | +------+------+ +---------+--------+
+------------+ | |
v v
+---------+ +---------+
| MongoDB | | Redis |
| events | | metrics |
+---------+ +---------+
PostgreSQL хранит текущее состояние заказов и является источником правды. Redis используется только для cache-aside чтений, короткоживущей аналитики и быстрого idempotency-фильтра. MongoDB хранит raw event payloads с гибкой структурой. RedPanda/Kafka развязывает синхронный API и фоновую обработку событий.
- Python 3.12
- FastAPI и Pydantic v2
- SQLAlchemy 2 async и Alembic
- PostgreSQL
- Redis
- MongoDB через Motor
- RedPanda как Kafka-compatible broker
- Docker Compose
- Ruff, MyPy и Pytest
- GitHub Actions CI
- Базовые Kubernetes manifests для application-сервисов
POST /orders— создать заказ.GET /orders/{order_id}— получить детали заказа через Redis cache-aside.GET /orders/{order_id}/status— получить статус заказа через Redis cache-aside.POST /orders/{order_id}/pay— отметить заказ как оплаченный.POST /orders/{order_id}/cancel— отменить заказ.GET /analytics/summary— получить eventually consistent аналитику за сегодня из Redis.GET /health— базовая проверка здоровья сервиса.
Пример создания заказа:
curl -X POST http://localhost:8000/orders \
-H 'Content-Type: application/json' \
-d '{
"user_id": "user-1",
"items": [
{"sku": "SKU-1", "quantity": 2, "price": "19.99"}
]
}'order-apiпринимает HTTP-команду.- Service layer валидирует бизнес-переход.
- PostgreSQL обновляется и коммитится.
- Связанные Redis-ключи инвалидируются при write operations.
- Доменное событие публикуется в
order.events. order-workerчитает событие, валидирует его через Pydantic, проверяет idempotency и сохраняет raw event в MongoDB.analytics-workerчитает тот же topic в отдельной consumer group и обновляет аналитику в Redis.- Невалидные события или события, которые не удалось обработать после retry, публикуются в
order.events.dlq.
Формат события:
{
"event_id": "uuid",
"event_type": "order.created",
"occurred_at": "2026-05-15T12:00:00Z",
"payload": {
"order_id": "string",
"user_id": "string",
"total_amount": "99.90"
}
}Поддерживаемые типы событий:
order.createdorder.paidorder.cancelledorder.delivered
API использует cache-aside для статуса и деталей заказа.
Для чтения:
- Проверить Redis.
- Если cache hit — вернуть данные из кеша.
- Если cache miss — прочитать PostgreSQL.
- Положить ответ в Redis с TTL.
- Вернуть ответ клиенту.
Для записи:
- Обновить PostgreSQL.
- Инвалидировать связанные Redis-ключи.
- Опубликовать Kafka event.
Redis keys:
order:{order_id}:status, TTL 60 секундorder:{order_id}:details, TTL 60 секундanalytics:summary:today, TTL 120-300 секундidempotency:{event_id}как быстрый worker-side duplicate filter
Redis никогда не является источником правды для состояния заказов.
order.events— доменные события, опубликованныеorder-api.order.events.dlq— невалидные события или события, которые не удалось обработать после ограниченного числа retry.
Consumer groups:
order-worker-groupanalytics-worker-group
Разные consumer groups нужны для того, чтобы order-worker и analytics-worker независимо получили один и тот же поток событий.
- PostgreSQL: текущее состояние заказов, позиции заказов и надежное хранение processed event ids.
- MongoDB: архив raw event payloads.
- Redis: cache-aside чтения заказов, аналитика и короткоживущие idempotency-фильтры.
- RedPanda/Kafka: асинхронная развязка сервисов через event stream.
При необходимости создай локальный .env из примера:
cp .env.example .envЗапуск всего стека:
make docker-upПолезные URL:
- API:
http://localhost:8000 - OpenAPI:
http://localhost:8000/docs - RedPanda Console:
http://localhost:8080 - внешний Kafka listener RedPanda:
localhost:19092
Если host-порт уже занят, переопредели его в .env, например:
POSTGRES_HOST_PORT=15432Остановка стека:
make docker-downУстановка зависимостей:
python -m pip install --upgrade pip
python -m pip install ".[dev]"Применить миграции:
make migrateЗапустить API локально:
make runЗапустить workers локально:
python -m order_platform.workers.order_worker
python -m order_platform.workers.analytics_workerПри локальном запуске без Docker инфраструктура должна быть доступна по значениям из .env или defaults из settings.py.
make test
make lint
make typecheckТесты покрывают service layer для order workflows, cache invalidation и analytics idempotency. Также есть API integration test через FastAPI ASGI transport с SQLite и in-memory fakes.
GitHub Actions запускается на push в main и pull requests.
Pipeline:
- Install dependencies.
ruff check .ruff format --check .mypypytestdocker build
Workflow: .github/workflows/ci.yml.
Директория k8s/ содержит базовые manifests только для application-сервисов:
order-apiDeploymentorder-apiServiceorder-workerDeploymentanalytics-workerDeployment- ConfigMap
- Secret example
PostgreSQL, Redis, MongoDB и RedPanda намеренно не описаны как production StatefulSet в Kubernetes. Manifests рассчитаны на подключение к внешней инфраструктуре или локально доступным сервисам.
Применить manifests:
kubectl apply -k k8s/Перед использованием нужно заменить image names и endpoints внешней инфраструктуры в k8s/configmap.yaml и k8s/secret.example.yaml.
src/order_platform/
api/ FastAPI app, routes and dependencies
core/ settings, enums and domain errors
db/ SQLAlchemy session helpers
infrastructure/ Redis, Kafka and MongoDB adapters
models/ SQLAlchemy models
repositories/ persistence access layer
schemas/ Pydantic request/response/event schemas
services/ business logic
workers/ Kafka consumer entrypoints
- Слоистую FastAPI backend architecture.
- PostgreSQL как authoritative state store.
- Redis cache-aside pattern с явной invalidation.
- Kafka-style event-driven processing через RedPanda.
- Отдельные consumer groups для независимых async workflows.
- MongoDB как raw event store.
- Durable idempotency через PostgreSQL плюс быстрый Redis-фильтр.
- DLQ handling после ограниченных retry.
- Docker Compose окружение для локальной разработки.
- CI quality gates через Ruff, MyPy, Pytest и Docker build.
- Kubernetes basics для stateless application workloads.
Проект намеренно компактный, но основные production concerns видны в коде. Для более строгих гарантий доставки событий стоит добавить transactional outbox: API будет записывать событие в outbox table внутри той же PostgreSQL transaction, а отдельный dispatcher будет публиковать события в Kafka/RedPanda.
Kubernetes manifests также намеренно не разворачивают базы данных и broker как production-инфраструктуру. В реальном окружении PostgreSQL, Redis, MongoDB и Kafka/RedPanda обычно берутся из managed-сервисов или отдельного infrastructure layer.