Проектирование распределённых систем — декомпозиция монолита на модули/сервисы (критерии границ), синхронное vs асинхронное взаимодействие (очереди, события), уровни масштабирования 100 → 10k RPS (кэш → реплики → шардинг), отказоустойчивость, наблюдаемость, что рисовать на архитектурной диаграмме. Use при проектировании архитектуры, обсуждении границ сервисов, очередей, масштабирования, отказоустойчивости.
Installs into .claude/skills of the current project.
Are you the author of System Design?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/vitammiin-system-design)
---
name: system-design
description: Проектирование распределённых систем — декомпозиция монолита на модули/сервисы (критерии границ), синхронное vs асинхронное взаимодействие (очереди, события), уровни масштабирования 100 → 10k RPS (кэш → реплики → шардинг), отказоустойчивость, наблюдаемость, что рисовать на архитектурной диаграмме. Use при проектировании архитектуры, обсуждении границ сервисов, очередей, масштабирования, отказоустойчивости.
---
# Навык: System Design
## Декомпозиция: монолит → модули → сервисы
Дефолт — **модульный монолит** (структура — `$backend-architecture`): модули с жёсткими границами внутри одного деплоя. Отдельный сервис выделяй, только когда у куска есть *своя* причина жить отдельно.
Критерии границы (модуля или сервиса):
- **Своя предметная область** (bounded context): свой словарь, свои инварианты. «Биллинг» и «Уведомления» — разные контексты; «UserUtils» — не граница.
- **Свои данные**: модуль владеет своими таблицами; чужие данные — только через его публичный API, не JOIN'ом в его схему.
- **Своя причина меняться**: релизится/масштабируется независимо (рассылки идут пачками ночью, API — днём).
- **Свой профиль нагрузки или команда**: CPU-тяжёлый рендер PDF рядом с латентно-чувствительным API — кандидат на вынос.
Пример: интернет-магазин → модули `catalog` (товары, поиск), `orders` (корзина, инварианты заказа), `billing` (платежи, вебхуки провайдера), `notifications` (email/push, ретраи). Первый кандидат в отдельный сервис — `notifications`: асинхронный, независимый ритм, безопасен при отставании. Плохая декомпозиция — по техслоям («сервис контроллеров», «сервис БД») или по CRUD-сущностям без инвариантов.
## Синхронно vs асинхронно
| Признак | Синхронно (HTTP/gRPC) | Асинхронно (очередь/событие) |
|---|---|---|
| Ответ нужен прямо в этом запросе | ✅ | — |
| Результат можно отдать позже (email, отчёт, вебхук) | — | ✅ |
| Вызываемый может лежать, а мы должны жить | — | ✅ (очередь буферизует) |
| Пики нагрузки надо сглаживать | — | ✅ |
| Несколько независимых потребителей одного факта | — | ✅ (событие, pub/sub) |
| «Проверь и сразу реши» в одной транзакции запроса | ✅ | — |
- **Команда** («сделай X», один получатель, важен результат) → очередь задач с подтверждением и ретраями (Redis Streams / RabbitMQ / SQS).
- **Событие** («X случилось», реагирует кто подписан) → pub/sub; producer не знает потребителей.
- Асинхронность тянет обязательства: идемпотентные потребители (at-least-once = дубли будут), DLQ для «ядовитых» сообщений, eventual consistency в UX («заказ обрабатывается»).
## Масштабирование: 100 → 10k RPS
1. **~100 RPS** — один сервер приложения + одна БД. Хватает индексов и вменяемых запросов. Не усложняй.
2. **~1k RPS** — сначала **кэш**: Redis cache-aside для горячих чтений, CDN для статики. Затем **горизонтально масштабируй stateless-приложение** за балансировщиком (сессии — в Redis/JWT, не в памяти процесса).
3. **~5k RPS** — узкое место обычно БД → **read-реплики** (чтения на реплики, записи в primary; учитывай лаг репликации), пул соединений (pgbouncer), тяжёлые операции — в фоновые очереди.
4. **~10k+ RPS** — **шардинг** (партиционирование записей по ключу: user_id, tenant). Последний ход, дорог в поддержке (cross-shard-запросы, решардинг); прежде чем шардить, проверь, что не хватило кэша, реплик и выноса горячих таблиц.
Каждый уровень включай, только когда упёрся **измеримо** (метрики), а не «на вырост».
## Отказоустойчивость (минимум)
Таймаут на каждый сетевой вызов → ретраи с экспонентой и jitter только для идемпотентных операций → circuit breaker к падающей зависимости → graceful degradation (рекомендации отвалились — каталог работает). Идемпотентность записи — ключи идемпотентности (`$api-design`).
## Наблюдаемость
- **Логи** — структурные (JSON), с `traceId`/`requestId`, сквозным через все сервисы.
- **Метрики** — RED на каждый эндпоинт и зависимость: Rate, Errors, Duration (p50/p95/p99, не среднее).
- **Трейсинг** — OpenTelemetry: один trace через сервисы и очереди; без него распределённую задержку не найти.
## Что рисовать на архитектурной диаграмме
(Строить — `$mermaid-diagrams` / `$drawio-diagrams`.)
- **Уровень C4-container**: по блоку на деплоймент-единицу — сервисы, БД, кэш, очереди, внешние API. Не по классу и не по функции.
- **Стрелки = вызовы**, с протоколом и направлением инициации: `API → Postgres (SQL)`, `API → Billing (HTTP, sync)`, `Orders → queue → Notifications (async)`. Sync и async визуально различай (сплошная/пунктир).
- **Границы доверия/сети** (VPC, публичное/приватное) — рамками; точки входа (LB, gateway) — явно.
- Не тащи всё в одну диаграмму: контекст — отдельно, контейнеры — отдельно, критичные потоки — sequence-диаграммой.