В этой статье я не теоретизирую. Каждый из блоков — это то, что работает. Если вы разработчик, который хочет думать как архитектор — этот список для вас.
Если вы архитектор, которому надоело рисовать схемы ради схем — этот список тоже для вас.
А если вы просто строите что-то серьёзное — сохранить, перечитать, внедрить. Это основа.
Системный дизайн — это не технология. Это способ мышления.
Масштабируемость — это про то, выдержит ли твоя система, если завтра трафик вырастет в 10 раз. Представь, что ты сделал сайт, и вдруг о тебе написали в СМИ. На сайт зашли не 100 человек, а 10 000. И вот тут начинается самое интересное: либо всё падает, либо всё работает как часы — если ты подумал о масштабировании.
Есть два варианта:
Вертикальное масштабирование — тупо добавляешь больше оперативки, CPU и надеешься, что машина выдержит. Просто, но до поры до времени.
Горизонтальное масштабирование — добавляешь ещё такие же машины, и они вместе обрабатывают нагрузку. Например, у тебя три сервера вместо одного, и балансировщик трафика их грамотно распределяет.
Нормальные взрослые системы всегда строят с прицелом на горизонтальное масштабирование. Это гибко и надёжно. Хотя вертикалка — тоже имеет место, особенно на старте.
1.2 Задержка (Latency)
Latency — это насколько быстро система отвечает на запрос. Пользователь кликает по кнопке, и если всё моментально — отлично. А если крутится спиннер 5 секунд — привет, отток клиентов.
Latency может зависеть от чего угодно: от физического расстояния до сервера (да-да), от перегруженной базы данных, от неоптимального кода. Поэтому часто используют:
CDN, чтобы статические файлы загружались с ближайшего узла.
Кеши, чтобы не лезть каждый раз в базу.
Асинхронные задачи, чтобы не тормозить главный поток.
Важно понимать: не всегда нужно гнаться за миллисекундами. Главное — чтобы всё ощущалось быстро и стабильно.
1.3 Пропускная способность (Throughput)
Throughput — это про то, сколько система может обработать за единицу времени. Например, ты можешь принимать 1000 запросов в секунду — это и есть твой throughput.
Скалируется он с добавлением ресурсов. Если ты увеличишь количество воркеров, поставишь Kafka вместо прямых вызовов, введёшь batch-обработку — throughput вырастет.
Пример: если у тебя загрузка видеофайлов, лучше принимать 100 файлов параллельно и обрабатывать их в очереди, чем делать всё по одному. Это и есть мышление через throughput.
1.4 Доступность (Availability)
Система может быть крутой, но если она лежит — всё, ты проиграл. Availability — это про то, чтобы система была доступна, когда нужна.
В продвинутых системах говорят не "всегда доступна", а "доступна 99.9% времени" — это уже стандарт. Чем больше девяток, тем круче:
99% = 3.5 дня простоя в год
99.9% = 8 часов
99.99% = 52 минуты
99.999% = 5 минут
Чтобы этого добиться, делают:
Репликации
Мониторинг и алерты
Failover-механизмы (один сервер падает — другой в бой)
1.5 Отказоустойчивость (Fault Tolerance)
Система должна уметь жить даже когда что-то ломается. Это не опция, это must-have.
Пример из жизни: сломался один микросервис, а вся система продолжает работать. Почему? Потому что была продумана архитектура — каждый компонент независим, умеет повторять попытки, есть fallback'и.
Отказоустойчивость строится на:
Повторных попытках (retry)
Таймаутах
Circuit Breaker’ах (чтобы не завалить зависимость)
Разделении зон ответственности
Если ты хочешь работать с реальными пользователями — будь готов к сбоям. Не «если случится», а «когда случится».
1.6 Согласованность (Consistency)
Вопрос на миллион: все ли пользователи видят одни и те же данные в одно и то же время? Если да — у тебя строгая согласованность (strong consistency). Если нет — это eventual consistency. Eventual consistency — это когда система гарантирует, что данные со временем станут одинаковыми во всех местах, но не обязательно мгновенно. Второй вариант чаще встречается в распределённых системах.
Представь, ты купил билет, а через секунду он снова появился в продаже — значит, у кого-то кэш отстал. Это и есть проблема согласованности.
Чтобы всё было в порядке, используют:
Транзакции (ACID) в SQL
Механизмы quorum и версии в NoSQL
События, которые разносятся по всем инстансам (например, Kafka)
Чем больше масштаб — тем сложнее сохранить консистентность. Но без неё — пользователи будут в шоке.
1.7 Надёжность хранения (Durability)
Durability — это про то, чтобы данные не исчезли после записи, даже если сервер упал, отключили электричество и т д.
Простой пример: ты купил товар, оплатил, тебе пришло подтверждение — значит, данные об этом заказе должны быть в системе железно. Если они пропадут — всё, это фейл на уровне бизнеса.
В реальных системах за durability отвечают:
Журнал транзакций (write-ahead log)
Подтверждение записи только после того, как данные физически попали на диск
Репликация в другие дата-центры (для катастрофоустойчивости)
Короче, если ты говоришь "успешно сохранено", — будь добр, реально сохрани.
1.8 Partition Tolerance (Толерантность к разделению)
Это когда твоя система не разваливается, если часть серверов вдруг перестала видеть друг друга по сети. Такое бывает постоянно: временные сбои, перегрузки, проблемы с маршрутизацией.
Вот тут появляется CAP-теорема, которая гласит:
В распределённой системе нельзя одновременно обеспечить Consistency, Availability и Partition Tolerance — максимум два из трёх.
Иными словами: если у тебя сеть «развалилась» на две части, ты должен выбрать — либо:
Система продолжит работать, но данные могут быть временно несогласованны (AP-система)
Либо остановишь приём запросов, но гарантируешь согласованность (CP-система)
Балансировщик — это как умный диспетчер, который решает, куда направить каждый входящий запрос.
Когда у тебя не один сервер, а несколько — кто-то должен раздавать запросы по ним так, чтобы ни один не перегружался. Вот этим и занимается Load Balancer.
Он может:
Распределять равномерно (round robin)
Направлять по нагрузке (least connections)
Следить за состоянием серверов (health checks)
Работать с failover — если один упал, перекидывает трафик на другие
API Gateway — это единая точка входа для всех клиентов.
Представь, у тебя 20 микросервисов. Без гейтвея пользователю пришлось бы напрямую стучаться в каждый. А так — всё идёт в одно место, а уже там решают, куда передать.
Что делает API Gateway:
Авторизация и аутентификация (JWT, OAuth)
Rate limiting (чтобы не заспамили)
Кеширование
Роутинг по сервисам
Конвертация протоколов (REST ↔ gRPC)
Это как секретарь, который проверяет, кто пришёл, и куда его направить. Примеры: Kong, Istio, Apigee и т д.
2.3 Web Server / App Server
Это фронтовая часть приложения. Web-сервер принимает HTTP-запросы, App-сервер обрабатывает бизнес-логику.
Иногда это одно и то же, особенно в небольших проектах.
Web server: NGINX, Caddy, Apache
App server: Express.js, Go Fiber, Django, Laravel и т.д.
Задача — принять запрос, разобрать, обработать, вернуть ответ. Здесь крутится основная логика твоего приложения.
2.4 Database — База данных
Сердце любой системы — база данных. Бывает двух типов:
SQL (PostgreSQL, MySQL): строго структурированная, мощные запросы, транзакции, сильная консистентность.
NoSQL (MongoDB, Cassandra, DynamoDB): гибкость, высокая масштабируемость, быстрая запись.
Выбор зависит от задачи. Если тебе нужно чёткое соблюдение правил (банковская система) — SQL. Если тебе нужно быстро писать и масштабировать (например, логирование) — NoSQL.
Почти всегда используют и то, и другое. Например, пользователи в SQL, события — в NoSQL.
2.5 Cache — Кэш (Redis, Memcached)
Кэш — это чтобы быстро, без БД, отдавать часто используемые данные.
Например, у тебя на главной странице список популярных постов. Зачем каждый раз лезть в базу, если можно положить результат в Redis и обновлять раз в минуту?
Типы кэшей:
In-memory (самый быстрый)
TTL (время жизни данных)
Слой над БД (например, кешировать результат запроса)
Redis — де-факто стандарт. Без кэша тяжело делать быстрые системы.
2.6 Message Queue — Очереди (Kafka, RabbitMQ)
Очередь нужна, когда тебе нужно отделить выполнение задачи от момента запроса.
Пример: пользователь загрузил файл. Не надо сразу его обрабатывать — положи задачу в очередь, пусть worker обработает в фоне.
Очереди дают:
Асинхронность
Надёжную доставку
Масштабируемость
Kafka хорош для большого потока событий, RabbitMQ — для задач с подтверждением доставки.
2.7 CDN — Content Delivery Network
CDN — это серверы, разбросанные по миру, которые отдают статический контент ближе к пользователю.
CSS, изображения, видео — всё это можно отдать через CDN, и пользователь из Ташкента к примеру получит файл быстрее, если он лежит на сервере в Дубае, а не в Лондоне.
Используют: Cloudflare, Akamai, Fastly, AWS CloudFront и другие.
CDN = меньше latency + меньше нагрузки на основную систему.
2.8 Blob Storage — Хранилище файлов
Blob-хранилище — это про сохранение больших неструктурированных файлов: фото, видео, документы, бэкапы.
Ты не хранишь это в БД — это дорого, медленно и глупо. Вместо этого — загружаешь в S3 (или аналоги) и сохраняешь ссылку.
Примеры: Amazon S3, Google Cloud Storage.
2.9 Service Mesh (Istio, Linkerd)
Когда у тебя десятки микросервисов, и каждый должен с кем-то говорить — появляется хаос. Service Mesh решает эту проблему.
Он перехватывает весь трафик между сервисами и управляет:
Авторизацией между сервисами
Мониторингом и логированием
Ретрайами и timeouts
A/B тестами
Service Mesh — это инфраструктура поверх инфраструктуры. В продвинутых системах — маст-хэв.
3. Управление данными (Data Management)
Data Management
3.1 Шардинг (Sharding)
Шардинг — это когда ты разбиваешь одну большую таблицу на несколько маленьких, чтобы разгрузить базу и упростить масштабирование.
Представь: у тебя 100 миллионов пользователей в одной таблице — БД тормозит. Решение? Делим по регионам или ID на 10 таблиц (шардов), и каждый сервер обрабатывает свою часть.
Когда у тебя 10+ шардов, любые изменения в структуре таблиц нужно делать во всех шард-базах. Это усложняет все, но при этом не является тупиком.
3.2 Репликация (Replication)
Репликация — это когда ты копируешь данные с одного сервера на другой, чтобы:
не потерять данные при сбое,
ускорить чтение,
балансировать нагрузку.
Есть два типа:
Master-Slave (Primary-Replica): один пишет, остальные читают.
Multi-Master: все могут писать (сложно, нужен контроль конфликтов).
Пример: у тебя одна основная база, и три реплики — пользовательские запросы на чтение идут в реплики, а запись — в мастер. Если мастер падает — один из реплик может стать новым мастером (failover).
3.3 Индексация (Indexing)
Индекс — это как оглавление в книге. Без него ты ищешь нужное значение, перелистывая страницы. С ним — сразу прыгаешь на нужную.
Индексы ускоряют поиск по полям (WHERE, JOIN, ORDER BY). Но! За всё надо платить:
Индексы занимают место
Замедляют INSERT/UPDATE/DELETE
Поэтому слепо ставить индекс на каждое поле — плохая идея. Нужно понимать, какие запросы самые частые, и индексировать только их.
3.4 Бэкапы и восстановление (Backup & Restore)
Ничего не вечно — даже самая крутая БД может рухнуть. Поэтому нужны регулярные бэкапы.
Варианты:
Snapshot (снимок всего состояния) — быстро восстановить всё как есть.
Incremental (разница с прошлого бэкапа) — экономия места.
Point-in-time recovery — восстановление до конкретного момента (например, за секунду до удаления таблицы).
Совет: бэкап, который не протестирован на восстановление — просто красивая папка.
3.5 Data Lake / Data Warehouse
Когда у тебя огромные объёмы данных (логов, кликов, покупок) — обычная БД уже не справляется.
Тогда используют:
Data Lake — сырые данные, всё подряд (S3, HDFS)
Data Warehouse — обработанные данные, пригодные для анализа (Snowflake, Redshift, BigQuery)
Это уже ближе к Big Data: ты не просто хранишь данные, а строишь аналитику, отчёты, ML-модели.
3.6 Schema Evolution — Эволюция схемы
В реальных проектах схема данных всегда меняется: добавляются поля, таблицы, меняются типы.
В SQL — это миграции (tools: Goose, Flyway, Liquibase)
В NoSQL — хаос, если не следить. Нужно делать versioning схемы вручную.
Важно не просто менять схему, а делать это безопасно: сначала добавить поле, потом начать его использовать, потом удалить старое. Всё — через фичефлаги и поэтапно.
4. Паттерны коммуникации (Communication Patterns)
Communication Patterns
4.1 Синхронная и асинхронная коммуникация (Sync vs Async)
Тут всё просто:
Синхронно — ты стучишь в сервис и ждёшь ответа. Пример: фронт делает GET /user/42, и ждёт JSON.
Асинхронно — ты кидаешь запрос и не ждёшь ответа прямо сейчас. Пример: пользователь загрузил фото, а его обрезка, сжатие, создание превью — всё пойдёт в фоне через очередь.
Синхронно — просто, быстро, но может тормозить весь процесс. Асинхронно — сложно отлаживать, но позволяет системе не «зависать».
Часто в реальных системах это микс: фронт работает синхронно, бэк между собой — асинхронно.
4.2 Pub/Sub — Публикация и Подписка
Pub/Sub — это когда один сервис публикует событие, а другие подписаны на него и реагируют.
Пример: пользователь сделал заказ → сервис «Платежи» отправил событие "оплата прошла" → подписаны сервисы "Доставка", "Личный кабинет", "Email-уведомления" и т.д.
События могут записываться в log (Kafka), из них можно строить цепочки (event sourcing), можно откатывать (replay), можно триггерить другие действия.
Плюсы:
Масштабируемо
Надёжно
Гибко
Минусы:
Сложно дебажить
Нужно уметь проектировать события
4.5 gRPC и Protobuf — Быстрые бинарные вызовы
Когда тебе нужно, чтобы микросервисы разговаривали быстро и без лишнего веса, ты используешь gRPC.
Это как REST, но через бинарный протокол Protobuf.
Автоматически создаются клиенты и серверы.
Меньше трафика, быстрее работает.
Минусы:
Не читается "глазами", как JSON
Нужно поддерживать .proto-файлы
Идеально подходит для внутренних вызовов между микросервисами, особенно в high-load системах.
4.6 WebSocket / Server-Sent Events (SSE)
Когда тебе нужен реальный real-time, обычный HTTP не подойдёт.
WebSocket — двусторонняя связь. Клиент и сервер могут отправлять данные в любую сторону в любой момент. Идеально для чатов, игр, торговых платформ.
SSE — сервер пушит данные на клиент, но клиент не может отправить обратно. Подходит для уведомлений, новостных лент.
Без этих штук не построишь по-настоящему живой интерфейс.
Если ты понимаешь, когда и какой паттерн использовать — ты уже на голову выше middle разработчика. Это важно не только для производительности, но и для устойчивости и читаемости архитектуры.
Деплой — это не просто "залить на сервер". Это про то, как не убить продакшен.
Основные стратегии:
Blue/Green: два окружения. Blue работает, ты выкатываешь в Green, переключаешь трафик — если баг, мгновенный откат.
Canary: сначала выкатываешь на 5% пользователей. Всё ок? Расширяешь на 50%, потом 100%.
Rolling: поочерёдно обновляешь по одной инстанции, без полного даунтайма.
Эти подходы позволяют минимизировать риски при каждом обновлении.
8.6 Secrets Management — Хранение секретов
Никогда не храни пароли, API-ключи, токены в .env, config.js, main.go.Они должны быть в надёжном и централизованном хранилище.
Инструменты:
HashiCorp Vault
AWS Secrets Manager
SOPS + GitOps
Управление доступами, автоматическая ротация — всё это критично для безопасности. Один слитый ключ — и вся инфраструктура может быть взломана.
DevOps и CI/CD — это двигатель твоей архитектуры. Даже если ты не DevOps-инженер, понимать это надо обязательно. Настоящие разработчики думают не только о коде, но и о том, как этот код живёт в бою.
9. Реальные архитектурные кейсы (Use Cases)
Use Cases
9.1 URL Shortener — Сервис коротких ссылок
Что нужно:
Генерация уникальных коротких ссылок
Быстрый редирект по ним
Защита от дубликатов и спама
Архитектура:
API Gateway → Web Server → Database (PostgreSQL / Redis)
Cache (Redis) — для мгновенного редиректа
TTL — для временных ссылок
Rate limiting — чтобы не спамили
Фишка: Redis часто можно использовать как основное хранилище, особенно если ссылки живут недолго.
9.2 Social Media Feed — Лента новостей
Что нужно:
Генерация ленты в реальном времени
Приоритизация контента (по интересам, лайкам, времени)
Бесконечный скроллинг
Архитектура:
Feed Generator Service
Fan-out on write (запись в ленты всех подписчиков) или Fan-out on read
Kafka / RabbitMQ — для пушей новых постов
Elasticsearch — для скоростного поиска
Redis — кеширование лент
Фишка: Не все ленты формируются "на лету" — часто они заранее сгенерированы в фоне.
9.3 E-Commerce — Интернет-магазин
Что нужно:
Структурированная база товаров, заказов, клиентов
Обработка заказов и платежей
Безопасность и отказоустойчивость
Архитектура:
Монолит или микросервисы (users, cart, checkout, payments)
SQL БД + Redis для кэшей
Payment Gateway (Stripe, Payme, Click)
Message Queue — обработка заказов в фоне
CDN — для изображений товаров
WAF + HTTPS + JWT
Фишка: Часто используют event-driven подход: заказ оформлен → событие → отправка письма, обновление склада, генерация накладной.
9.4 Chat App — Чат/мессенджер
Что нужно:
Мгновенная доставка сообщений
Онлайн/офлайн статус
Группы, каналы, файлы
Архитектура:
WebSocket сервер (на Go, Elixir, Node)
Redis / NATS — для pub/sub
Kafka — лог всех сообщений
Blob Storage — для файлов
PostgreSQL / MongoDB — база сообщений
Push-уведомления (Firebase, OneSignal)
Фишка: Сообщения сохраняются асинхронно, главное — быстрая доставка.
9.5 Video Streaming — Видео-платформа
Что нужно:
Быстрая загрузка и просмотр
Адаптивное качество (в зависимости от сети)
Авторизация, доступ по подписке
Архитектура:
Frontend (React, Flutter) → CDN
Transcoder (FFmpeg в очереди) — сжимает и нарезает видео
Storage (S3) — хранение роликов
API Gateway — проверка доступа
HLS / DASH — потоковая передача
Metrics — смотреть, где тормозит
Фишка: Видео обычно режется на сегменты и хранится по качеству, CDN сам выбирает нужный поток.
Фишка: Вся система построена на событиях и гео-обработке. Важно держать состояние "в пути" и "доступен" в real-time.
9.7 SaaS-платформа с мультиарендой
Что нужно:
Обслуживать много компаний (тенантов)
Изоляция данных
Управление подписками
Архитектура:
Tenant-aware микросервисы
Shared DB (с фильтрами по tenant_id) или отдельная БД на каждого
Stripe / Billing-сервис
RBAC — разграничение прав
CI/CD с tenant migration
Фишка: Тут важно соблюдать баланс: между удобством управления и изоляцией, безопасностью данных.
10. Производительность и надёжность (Performance & Reliability)
Performance & Reliability
Это финальный, но не по значимости блок. Всё, что мы до этого проектировали — архитектура, очереди, микросервисы — работает до тех пор, пока система справляется с нагрузкой и не ломается от мелочей. А это уже отдельное искусство.
10.1 Load Testing — Нагрузочное тестирование
Как узнать, сколько запросов в секунду выдерживает твой сервис? Или когда начнётся деградация? Ответ — нагрузочное тестирование.
Ты берёшь инструмент (например, k6, JMeter или Locust) и симулируешь:
тысячу пользователей, открывающих страницу одновременно
1000 платежей в секунду
загрузку 500 файлов за минуту
Главное — не ждать реальной катастрофы, а смоделировать её заранее.
10.2 Stress Testing — Тестирование на пределе
Это уже не просто "нагрузка", а искусственное создание хаоса. Цель — увидеть, как система себя ведёт при полном п...
Примеры:
В два раза больше трафика, чем обычно
Отключили базу
Все очереди переполнены
Закончилась память
Важно не просто "выжить", а дать предсказуемый отказ: с ошибкой 503, с алертом, с логом. А не просто "ничего не работает".
10.3 Capacity Planning — Планирование ёмкости
Это про то, чтобы не гадать, а точно знать, сколько тебе нужно серверов, памяти, дисков, чтобы система работала стабильно.
Пример: ты знаешь, что при 5000 одновременных пользователей CPU идёт в потолок — и планируешь масштабирование заранее.
Используется:
Исторические метрики (Prometheus)
Прогнозирование по нагрузке
Тесты на грани (см. выше)
10.4 Error Budgets — Бюджет ошибок
Этот подход взят из SRE. Он помогает балансировать между "хочу выкатывать фичи" и "хочу, чтобы всё было стабильно".
Принцип:
У тебя есть, например, 99.9% SLO (см. ниже)
Значит, ты можешь позволить себе 0.1% ошибок или даунтайма
SLO (Service Level Objective) — твоя цель: "должно быть не ниже 99.9%"
SLA (Agreement) — договор с клиентом: "если ниже 99.5% — возвращаем деньги"
Это язык надёжности. Без него ты не можешь ни планировать, ни оправдываться.
10.6 Chaos Engineering — Инженерия хаоса
Суть простая: ты сам ломаешь систему — чтобы убедиться, что она не развалится.
Netflix, например, использует Chaos Monkey — сервис, который случайно отключает инстансы в продакшене, чтобы проверить устойчивость.
Формула простая:
Упал один сервис → должен быть failover
Сломалась база → остальная система должна не умереть
Пропала связь между датацентрами → должна быть деградация, а не апокалипсис
А вот и конец :) Пока что. Позже, возможно, загружу визуальную часть, где будут перечислены все концепции, в сжатом виде. Тот, кто всё понял молодец! А кто не понял может перечитать хотя бы названия концепций и попробовать визуализировать каждую из них. Не нужно бояться перечисленных технологий. Главное понять, что именно они делают. Ведь по сути все технологии занимаются обработкой данных, просто делают это по разному так, как их себе представил автор :) Обязательно делитесь своим опытом и рассказывайте, какие технологии применяли в своей работе будет интересно сравнить подходы!
*Добавил шпаргалку для тех, кто будет двигаться в этом направлении.