System Design Interview

Введение

System Design интервью - это один из ключевых этапов собеседования на позиции senior+ инженеров. В отличие от алгоритмических задач, здесь нет “правильного” ответа. Интервьюер оценивает ваше умение анализировать требования, проектировать масштабируемые системы, обсуждать trade-off’ы и коммуницировать свои решения.

Эта методичка построена на основе опыта прохождения интервью и классических ресурсов: Designing Data-Intensive Applications Мартина Клеппманна и System Design Interview Алекса Сю. Основная техническая база по системному дизайну находится в заметке System Design - здесь мы фокусируемся именно на процессе прохождения интервью.

Summary

Что вы найдёте в этой заметке:

  • Фреймворк прохождения интервью из 5 фаз
  • Два полных разбора: WhatsApp (write-heavy, real-time) и URL Shortener (read-heavy, simple)
  • Инфраструктурный реализм: как выглядит система в реальном датацентре
  • Чек-лист подготовки и типичные ошибки

Фреймворк прохождения интервью

Что оценивает интервьюер

System Design интервью - это не экзамен на знание конкретных технологий. Интервьюер оценивает четыре компетенции:

КомпетенцияЧто проверяетсяКак проявить
Анализ проблемыУмеете ли вы задавать правильные вопросы, а не сразу предлагать решениеНачинайте с уточнения требований
Знание системного дизайнаПонимаете ли вы масштабирование, отказоустойчивость, trade-off’ыОбъясняйте почему вы выбрали именно это решение
КоммуникацияУмеете ли вы структурировать мысли и вести диалогГоворите вслух, рисуйте диаграммы, задавайте вопросы
Анализ trade-off’овВидите ли вы плюсы и минусы каждого решенияВсегда предлагайте 2-3 альтернативы и объясняйте выбор

Important

Интервьюер оценивает процесс мышления, а не конечное решение. Нет “правильного” ответа - есть обоснованный подход с учётом ограничений.


Пятифазный фреймворк

Каждое System Design интервью длится 45-60 минут. Оптимальное распределение времени:

ФазаВремяЦель
1. Требования2-3 минУточнить функциональные и нефункциональные требования
2. Оценка масштаба5-10 минПосчитать QPS, хранилище, пропускную способность
3. Высокоуровневый дизайн10-15 минНарисовать архитектуру из 3-5 компонентов
4. Углубление15-25 минРазобрать 2-3 компонента детально, обсудить trade-off’ы
5. Завершение3-5 минОбсудить мониторинг, сценарии отказа, масштабирование

Summary

60 минут = 3 мин требования + 10 мин оценка + 15 мин HLD + 25 мин deep dive + 5 мин wrap-up + 2 мин буфер

Фаза 1: Сбор требований

Что делать:

  • Задавать уточняющие вопросы до того, как начнёте проектировать
  • Определить функциональные требования (что система делает)
  • Определить нефункциональные требования (как система работает)

Что спросить у интервьюера:

  • “Какой масштаб мы рассматриваем - миллионы или миллиарды пользователей?”
  • “Какие функции обязательны, а какие опциональны?”
  • “Есть ли ограничения по latency или доступности?”
  • “Нужна ли поддержка мобильных приложений и веба одновременно?”

Типичные ошибки:

  • Начинать проектировать без уточнения требований
  • Предполагать требования вместо того, чтобы спросить
  • Упускать нефункциональные требования (доступность, консистентность)

Пример диалога:

Кандидат: “Прежде чем начать, хочу уточнить несколько моментов. Для скольких пользователей мы проектируем систему?”

Интервьюер: “Допустим, 100 миллионов DAU.”

Кандидат: “Отлично. А какие функции обязательны - только отправка сообщений или также групповые чаты и медиа?”

Фаза 2: Оценка масштаба

Что делать:

  • Сделать back-of-the-envelope расчёты
  • Посчитать QPS (queries per second)
  • Оценить объём хранилища
  • Оценить пропускную способность сети

Как считать:

  • DAU × действий в день ÷ 86400 = write QPS
  • Read QPS обычно в 5-10 раз выше write QPS
  • Объём = количество записей × средний размер записи
  • Пропускная способность = QPS × размер запроса

Пример расчёта для мессенджера:

DAU: 200 миллионов
Сообщений на пользователя в день: 10
Всего сообщений в день: 2 миллиарда
Write QPS: 2B ÷ 86400 ≈ 23 000
Read QPS: 23 000 × 10 ≈ 230 000 (каждое сообщение читают ~10 человек)
Средний размер сообщения: 100 байт
Хранилище в день: 2B × 100B = 200 ГБ
Хранилище в год: 200 ГБ × 365 ≈ 73 ТБ

Типичные ошибки:

  • Не показывать расчёты на доске / в редакторе
  • Забывать про пиковую нагрузку (peak может быть в 2-3 раза выше среднего)
  • Не учитывать рост (система будет работать не один день)

Фаза 3: Высокоуровневый дизайн

Что делать:

  • Нарисовать архитектуру из 3-5 компонентов
  • Определить API endpoints
  • Определить модель данных
  • Показать поток данных между компонентами

Принципы:

  • Начинайте просто - 3-5 прямоугольников с подписями
  • Используйте стандартные компоненты: Load Balancer, API Gateway, Application Server, Database, Cache, Message Queue
  • Не углубляйтесь в детали - это только высокоуровневый взгляд

Пример архитектуры (мессенджер):

┌─────────┐     ┌─────────────┐     ┌─────────────────┐     ┌──────────┐
│ Client  │────→│ API Gateway │────→│ App Servers     │────→│ Database │
└─────────┘     └─────────────┘     └─────────────────┘     └──────────┘
                                           │
                                           ↓
                                    ┌─────────────┐
                                    │ Message     │
                                    │ Queue       │
                                    └─────────────┘

Типичные ошибки:

  • Переусложнять архитектуру с первого шага
  • Не объяснять поток данных
  • Пропускать API или модель данных

Фаза 4: Углубление

Что делать:

  • Выбрать 2-3 компонента для детального разбора
  • Обсудить trade-off’ы для каждого решения
  • Объяснить выбор конкретной технологии

Как выбрать компоненты:

  • Спросите интервьюера: “В какую часть системы стоит углубиться?”
  • Если интервьюер не направляет, выберите наиболее интересные компоненты:
    • Для мессенджера: доставка сообщений, хранение, масштабирование БД
    • для URL shortener: генерация коротких ссылок, кэширование, выбор БД

Структура обсуждения trade-off’ов:

  1. “У нас есть несколько подходов…”
  2. “Подход A даёт X, но требует Y…”
  3. “Подход B даёт Z, но сложнее в настройке…”
  4. “Я выбираю подход A, потому что…”

Пример trade-off (выбор БД):

“Для хранения сообщений можно использовать SQL или NoSQL. SQL даёт ACID и сложные запросы, но сложнее масштабировать горизонтально. NoSQL легко шардировать, но eventual consistency может означать, что сообщения временно не видны всем участникам чата. Для мессенджера я бы выбрал NoSQL с настройкой strong consistency для критичных операций.”

Типичные ошибки:

  • Не обсуждать альтернативы
  • Защищать своё решение эмоционально вместо того, чтобы аргументировать
  • Углубляться в нерелевантные детали (например, специфику конкретной версии PostgreSQL)

Фаза 5: Завершение

Что делать:

  • Обсудить мониторинг и метрики
  • Рассмотреть сценарии отказа
  • Упомянуть будущее масштабирование

Мониторинг:

  • Какие метрики отслеживать (latency, error rate, throughput)
  • Какие алерты настроить
  • Какие дашборды использовать

Сценарии отказа:

  • “Что если упадёт одна нода БД?”
  • “Что если откажет центр обработки данных?”
  • “Как обеспечить zero-downtime deployment?”

Будущее масштабирование:

  • “Если пользователей станет в 10 раз больше…”
  • “Если добавим новую функцию (например, видеозвонки)…”

Типичные ошибки:

  • Забывать про мониторинг
  • Не обсуждать failure scenarios
  • Заканчивать слишком быстро без wrap-up

Коммуникационные паттерны

Что говорить на каждой фазе

Начало интервью:

“Спасибо за задачу. Прежде чем начать проектировать, хочу уточнить несколько требований. Так я смогу предложить более точное решение.”

При переходе между фазами:

“Требования уточнены. Давайте оценим масштаб системы…” “Расчёты готовы. Теперь нарисую высокоуровневую архитектуру…” “Архитектура готова. В какую часть системы стоит углубиться?”

При обсуждении trade-off’ов:

“Здесь есть несколько подходов. Давайте рассмотрим плюсы и минусы каждого…” “Я склоняюсь к варианту X, потому что… Но при условии Y вариант Z тоже имеет смысл.”

При получении pushback от интервьюера:

“Хороший вопрос. Давайте подумаем, как это повлияет на архитектуру…” “Вы правы, этот подход имеет ограничение. Альтернатива - …”

Как обрабатывать неизвестные вопросы

Если интервьюер спрашивает о технологии, которую вы не знаете:

“Честно говоря, я не работал с X напрямую. Но я знаю, что в этой области есть подходы Y и Z. Если X решает похожую задачу, я бы изучил его trade-off’ы перед выбором.”

Это показывает:

  • Честность (не выдумываете знания)
  • Гибкость мышления (готовы изучить новое)
  • Понимание домена (знаете альтернативы)

Типичные ошибки и как их избежать

Ошибка 1: Начать решать без уточнения требований

Почему это проблема: Вы можете спроектировать систему для неправильного масштаба или упустить критичные требования.

Как избежать: Всегда начинайте с вопросов. Даже если требования кажутся очевидными, уточните масштаб и приоритеты.

Ошибка 2: Игнорировать нефункциональные требования

Почему это проблема: Доступность 99.9% и 99.999% - это разные архитектуры. eventual consistency и strong consistency - разные решения.

Как избежать: Явно спросите про availability, consistency, latency требования.

Ошибка 3: Переусложнять с первого шага

Почему это проблема: Сложная архитектура из 15 компонентов трудно объяснить и отлаживать. Интервьюер оценивает процесс, а не количество компонентов.

Как избежать: Начинайте с 3-5 компонентов. Усложняйте только там, где это обосновано.

Ошибка 4: Не обсуждать trade-off’ы

Почему это проблема: Каждое решение имеет цену. Если вы не обсуждаете альтернативы, интервьюер не видит глубины вашего понимания.

Как избежать: Для каждого ключевого решения предлагайте 2-3 альтернативы и объясняйте выбор.

Ошибка 5: Молчать или думать про себя

Почему это проблема: Интервьюер не видит ваш процесс мышления. Вы можете прийти к правильному ответу, но не получить credit за путь.

Как избежать: Думайте вслух. Объясняйте каждый шаг. Рисуйте на доске или в редакторе.

Ошибка 6: Не оценивать масштаб

Почему это проблема: Без расчётов вы не можете обосновать выбор технологий. SQL может быть нормально для 1000 пользователей, но не для 100 миллионов.

Как избежать: Всегда делайте back-of-the-envelope расчёты. Показывайте их на доске.

Ошибка 7: Забывать про мониторинг и отказы

Почему это проблема: Production система без мониторинга - это чёрный ящик. Без плана отказов - это система, которая упадёт при первой проблеме.

Как избежать: Завершайте интервью обсуждением monitoring, alerting, failure scenarios.

Ошибка 8: Защищать ошибочное решение

Почему это проблема: Интервьюер может указывать на реальные проблемы. Защита “до последнего” показывает негибкость.

Как избежать: Будьте открыты к feedback. “Вы правы, это создаёт bottleneck. Давайте пересмотрим этот компонент.”

Ошибка 9: Не спрашивать направления у интервьюера

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

Как избежать: Спрашивайте: “В какую часть системы стоит углубиться?” или “Что для вас наиболее интересно в этом дизайне?”


Разбор: WhatsApp Messenger

В этом разборе мы проходим все пять фаз интервью на примере проектирования мессенджера, похожего на WhatsApp. Требования взяты из реального домашнего задания и адаптированы для формата интервью.

Фаза 1: Требования

Диалог с интервьюером:

Кандидат: “Прежде чем начать, хочу уточнить масштаб и функции. Для скольких пользователей мы проектируем?”

Интервьюер: “200 миллионов DAU.”

Кандидат: “Какие функции обязательны? Отправка текстовых сообщений, групповые чаты, медиа?”

Интервьюер: “Текстовые сообщения, групповые чаты до 256 участников, изображения и видео, статус доставки и прочтения, синхронизация между устройствами.”

Кандидат: “Есть ли требования к latency и доступности?”

Интервьюер: “Доставка сообщений менее 200 мс, доступность 99.99%.”

Функциональные требования:

  • Отправка и получение текстовых сообщений в личных и групповых чатах
  • Групповые чаты до 256 участников
  • Статус сообщений: отправлено, доставлено, прочитано
  • Онлайн / оффлайн статус пользователей
  • Отправка медиа: изображения, видео, документы
  • Синхронизация между несколькими устройствами

Нефункциональные требования:

  • Доступность: 99.99%
  • Latency: менее 200 мс на доставку сообщения
  • Консистентность: сообщения должны приходить в порядке отправки
  • Масштаб: 200 миллионов DAU

Фаза 2: Оценка масштаба

Диалог:

Кандидат: “Давайте оценим масштаб. Сколько сообщений отправляет один пользователь в день?”

Интервьюер: “В среднем 10 сообщений в день.”

Кандидат: “Отлично. Тогда общий объём:”

Расчёты:

DAU: 200 000 000
Сообщений на пользователя в день: 10
Всего сообщений в день: 2 000 000 000

Write QPS: 2 000 000 000 ÷ 86 400 ≈ 23 000
Read QPS: 23 000 × 10 ≈ 230 000
(каждое сообщение читают примерно 10 человек в среднем)

Средний размер текстового сообщения: 100 байт
Хранилище текстов в день: 2B × 100B = 200 ГБ
Хранилище текстов в год: 200 ГБ × 365 ≈ 73 ТБ

Медиа:
- Изображения: 10% сообщений, средний размер 1 МБ
- Видео: 2% сообщений, средний размер 10 МБ
- Хранилище медиа в день: ~40 ТБ

Important

Пиковая нагрузка может быть в 2-3 раза выше средней. Для peak write QPS считаем ~70 000.


Фаза 3: Высокоуровневый дизайн

Архитектура:

┌─────────┐     ┌─────────────┐     ┌─────────────────┐     ┌──────────┐
│ Client  │────→│ API Gateway │────→│ App Servers     │────→│ Database │
│ (Mobile │     │ (Rate Limit,│     │ (WebSocket      │     │ (Messages,│
│  Web,   │     │  Auth)      │     │  handlers,      │     │  Users,   │
│ Desktop)│     │             │     │  business logic)│     │  Chats)   │
└─────────┘     └─────────────┘     └─────────────────┘     └──────────┘
                                              │
                                              ↓
                                       ┌─────────────┐
                                       │ Message     │
                                       │ Queue       │
                                       │ (Kafka /    │
                                       │  RabbitMQ)  │
                                       └─────────────┘
                                              │
                                              ↓
                                       ┌─────────────┐
                                       │ Push        │
                                       │ Notification│
                                       │ Service     │
                                       └─────────────┘
                                              │
                                              ↓
                                       ┌─────────────┐
                                       │ Object      │
                                       │ Storage     │
                                       │ (S3)        │
                                       └─────────────┘

API Design:

MethodEndpointОписание
POST/messagesОтправить сообщение
GET/messages?chat_id={id}&limit=50Получить сообщения чата
GET/users/{id}/statusПолучить статус пользователя
POST/media/uploadЗагрузить медиафайл
GET/media/{id}Получить медиафайл
POST/chatsСоздать чат
GET/chats/{id}/membersПолучить участников чата

Модель данных:

users
  - id (PK)
  - username
  - phone_number
  - last_seen
  - public_key (для E2E encryption)
  - created_at

chats
  - id (PK)
  - type (1:1 / group)
  - name (для групп)
  - created_at

chat_members
  - chat_id (FK)
  - user_id (FK)
  - joined_at
  - role (admin / member)

messages
  - id (PK)
  - chat_id (FK)
  - sender_id (FK)
  - content (текст или ссылка на медиа)
  - type (text / image / video / file)
  - sequence_number (для порядка в чате)
  - status (sent / delivered / read)
  - created_at

media
  - id (PK)
  - message_id (FK)
  - url (ссылка на S3)
  - type (image / video / file)
  - size
  - created_at

Фаза 4: Углубление

Тема 1: Доставка сообщений в реальном времени

Диалог:

Кандидат: “Ключевой вопрос - как обеспечить доставку сообщений менее чем за 200 мс. Для активных пользователей я бы использовал WebSocket соединения.”

Интервьюер: “А что делать с пользователями, которые оффлайн?”

Кандидат: “Хороший вопрос. Для оффлайн-пользователей сообщения сохраняются в базе данных. Когда пользователь подключается, мы отправляем все пропущенные сообщения.”

Подход:

  • Активные пользователи: WebSocket соединение для real-time доставки
  • Оффлайн пользователи: сообщения сохраняются в БД, доставляются при подключении
  • Статусы: sent → delivered → read

Trade-off:

  • WebSocket даёт низкую latency, но требует держать много открытых соединений
  • Long polling проще, но latency выше
  • Выбор: WebSocket для real-time, fallback на long polling

Тема 2: Масштабирование базы данных

Диалог:

Кандидат: “С 23 000 write QPS и 230 000 read QPS одна нода БД не справится. Нужно шардирование.”

Интервьюер: “По какому ключу будем шардировать?”

Кандидат: “Есть два подхода. По chat_id - история чата остаётся на одном шарде, что упрощает чтение. По user_id - нагрузка распределяется равномернее. Я бы выбрал шардирование по chat_id с репликацией для чтения.”

Подход:

  • Шардирование по chat_id (консистентность истории чата)
  • Read replicas для снижения нагрузки на чтение
  • Кэширование последних сообщений в Redis

Trade-off:

  • Шардирование по chat_id: проще чтение, но hot chats создают hotspot
  • Шардирование по user_id: равномерная нагрузка, но чтение истории требует запросов к нескольким шардам
  • Выбор: Шардирование по chat_id + мониторинг hotspot’ов

Тема 3: Хранение медиа

Диалог:

Кандидат: “Медиафайлы занимают значительно больше места, чем текст. 40 ТБ в день - это требует отдельного подхода.”

Интервьюер: “Как бы вы хранили медиа?”

Кандидат: “Object storage, например S3. Файлы загружаются напрямую в S3 через presigned URL. В сообщении хранится только ссылка. Для быстрой доставки используем CDN.”

Подход:

  • Object Storage (S3) для долговременного хранения
  • Presigned URLs для загрузки напрямую из клиента
  • CDN для глобальной доставки
  • Сжатие изображений и транскодирование видео

Trade-off:

  • Object storage дешевле, но latency выше, чем у локального хранилища
  • CDN ускоряет доставку, но добавляет стоимость
  • Выбор: S3 + CDN для production, локальное хранилище для недавних файлов

Тема 4: Синхронизация между устройствами

Диалог:

Кандидат: “Пользователь может быть одновременно на телефоне и на компьютере. Нужна синхронизация.”

Интервьюер: “Как бы вы это реализовали?”

Кандидат: “Каждое устройство поддерживает WebSocket соединение. Для синхронизации используем sequence_number сообщений. Каждое устройство знает последнее прочитанное sequence_number и запрашивает только новые сообщения.”

Подход:

  • Отдельное WebSocket соединение на устройство
  • Sequence numbers для порядка сообщений
  • sync_protocol: last_seen_sequence_number на устройстве
  • Conflict resolution: server wins (last write)

Trade-off:

  • Много соединений на пользователя = больше ресурсов сервера
  • Но необходимо для кросс-девайс опыта
  • Выбор: Поддержка до 3-5 устройств на пользователя с балансировкой нагрузки

Фаза 5: Завершение

Мониторинг:

МетрикаПочему важна
Message delivery latency (p50, p95, p99)Проверяем SLA в 200 мс
Failed message rateДолжно быть менее 0.01%
Active WebSocket connectionsПланирование capacity
Storage growth rateПланирование расширения
Error rate by componentБыстрое обнаружение проблем

Сценарии отказа:

ОтказРешение
Нода БД недоступнаПромоутить read replica в master
Сервер WebSocket упалКлиент переподключается к другому серверу
Message Queue недоступнаЛокальная буферизация с retry
Датацентр недоступенMulti-region replication, failover

Будущее масштабирование:

  • Федерация: поддержка сообщений между разными сервисами (interoperability)
  • End-to-end encryption: Signal Protocol для приватности
  • Исчезающие сообщения: автоудаление через заданное время
  • Голосовые сообщения и видеозвонки: WebRTC интеграция

Инфраструктурный реализм

В System Design интервью важно показать, что вы понимаете не только абстрактную архитектуру, но и реальные физические ограничения. Этот раздел покрывает инфраструктурные детали, которые часто спрашивают на интервью или которые отличают хорошего кандидата.

Физическая инфраструктура

Стойки и серверы

Стандартная серверная стойка имеет высоту 42U (units). Каждый unit - это 1.75 дюйма (44.45 мм).

ПараметрТипичное значение
Высота стойки42U (~1.8 метра)
Серверов в стойке20-40 (в зависимости от высоты сервера: 1U или 2U)
Мощность стойки5-10 кВт
Сетевой коммутатор10-100 Gbps (top-of-rack)

Info

1U сервер занимает 1 unit, 2U - два unit’а. Более мощные серверы обычно 2U из-за большего количества дисков и лучшего охлаждения.

Диски и хранилище

ТипЁмкостьIOPSЗадержкаПрименение
NVMe SSD1-8 ТБ~500 000~50 мксБазы данных, hot data
SATA SSD1-8 ТБ~100 000~100 мксБазы данных, кэши
HDD8-20 ТБ~200~5 мсХолодное хранение, бэкапы

Ключевое наблюдение для интервью:

Important

Разница в latency между RAM и SSD - в 1000 раз. Между SSD и HDD - ещё в 50 раз. Это определяет архитектурные решения: hot data в RAM/SSD, cold data на HDD.

Конфигурация дисков в стойке:

  • Типичный сервер базы данных: 8-16 NVMe SSD по 4 ТБ = 32-64 ТБ
  • Типичный сервер хранения: 12-24 HDD по 16 ТБ = 192-384 ТБ
  • Одна стойка с 20 серверами БД: ~640 ТБ - 1.3 ПБ SSD
  • Одна стойка с 20 серверами хранения: ~3.8 - 7.7 ПБ HDD

Сеть и latency

РасстояниеЗадержкаПример
Внутри датацентра< 1 мсДва сервера в одном здании
Внутри региона5-20 мсВосточное побережье США
Между регионами20-50 мсВосточное и западное побережье
Между континентами50-200 мсСША - Европа
Вокруг земного шара150-300 мсСША - Азия

Пропускная способность:

ПодключениеПропускная способность
1 Gbps~125 МБ/с
10 Gbps~1.25 ГБ/с
40 Gbps~5 ГБ/с
100 Gbps~12.5 ГБ/с

Info

В интервью полезно знать: 10 Gbps - стандарт для современных датацентров. Один сервер с 10 Gbps может передать 1 ТБ за ~15 минут.

Память

ТипЁмкость на серверЗадержка
DDR4 RAM64-512 ГБ~100 нс
DDR5 RAM128-1024 ГБ~80 нс

Important

RAM в 1000 раз быстрее SSD. Это объясняет, почему кэширование критично для производительности.


Масштабы времени

Эта таблица помогает интуитивно понять разницу в скорости операций:

ОперацияВремяЧеловеческий масштаб
Чтение L1 кэша1 нс1 секунда
Чтение L2 кэша4 нс4 секунды
Чтение RAM100 нс1.5 минуты
Чтение SSD100 мкс1.5 дня
Чтение HDD5 мс2.5 месяца
Сеть (внутри DC)0.5 мс2.5 недели
Сеть (межконтинентальная)150 мс5 лет

Summary

Если бы операции в компьютере происходили в человеческом масштабе, чтение с HDD заняло бы 2.5 месяца, а сетевой запрос в другой континент - 5 лет. Это объясняет, почему кэширование и локальность данных так важны.


Стоимость хранения

Тип храненияСтоимость за ГБ/месяц
RAM$3-5
SSD$0.10-0.20
HDD$0.01-0.02
S3 Standard$0.023
S3 Glacier$0.004

Пример расчёта для интервью:

“Наш мессенджер генерирует 200 ГБ текстовых сообщений в день и 40 ТБ медиа. За год - 73 ТБ текста и 14.6 ПБ медиа. Если хранить текст в SSD (11 000/мес. Медиа в S3 Standard (336 000/мес. Итого ~$350 000/мес только на хранение.”

Important

На интервью не нужно знать точные цены, но понимание порядка величин (RAM в 100 раз дороже SSD, SSD в 10 раз дороже HDD/S3) помогает обосновывать архитектурные решения.


Network Policy

На уровне System Design интервью Network Policy - это не настройка YAML, а понимание принципов сегментации сети.

Ключевые концепции

Микросегментация:

  • Разделение сети на маленькие сегменты
  • Каждый сервис находится в своём сегменте
  • Трафик между сегментами контролируется явно

Zero Trust:

  • Никогда не доверяй, всегда проверяй
  • Каждое соединение аутентифицируется
  • Даже внутри датацентра трафик проверяется

K8s NetworkPolicy:

  • Определяет, какие pod’ы могут общаться друг с другом
  • Ingress rules: кто может обращаться К этому pod’у
  • Egress rules: куда этот pod может обращаться
  • Default deny: блокировать весь трафик, кроме явно разрешённого

AWS Security Groups:

  • Stateful firewall на уровне инстанса
  • Inbound rules: разрешить трафик от определённых источников
  • Outbound rules: разрешить трафик к определённым назначениям

Service Mesh (Istio / Linkerd):

  • mTLS между сервисами
  • Политики трафика на уровне сервисов
  • Observability: кто с кем общается

Info

На интервью достаточно сказать: “Я бы использовал микросегментацию сети с принципом zero trust. В Kubernetes это NetworkPolicy с default deny. В облаке - Security Groups. Для межсервисного взаимодействия - service mesh с mTLS.”


RBAC (Role-Based Access Control)

Ключевые концепции

Принцип наименьших привилегий:

  • Давать минимум необходимых прав
  • Каждый компонент имеет доступ только к тому, что ему нужно
  • Если сервис читает из БД сообщений, у него нет прав на удаление пользователей

K8s RBAC:

  • Role: определяет права внутри namespace
  • ClusterRole: определяет права во всём кластере
  • RoleBinding: связывает Role с пользователями / группами / service accounts
  • ServiceAccount: идентификация для pod’ов

IAM (AWS / Azure / GCP):

  • Policies: JSON-документы, определяющие права
  • Roles: принимаются сущностями (пользователи, сервисы, EC2 инстансы)
  • Groups: набор пользователей с общими правами

ABAC (Attribute-Based Access Control):

  • Доступ на основе атрибутов (отдел пользователя, время суток, локация)
  • Более гибкий, чем RBAC, но сложнее в управлении

Info

На интервью достаточно сказать: “Я бы применил принцип наименьших привилегий. В Kubernetes - RBAC с отдельными ServiceAccount для каждого сервиса. В облаке - IAM roles с narrowly scoped policies.”


Почему это важно на интервью

Интервьюер оценивает:

  • Понимаете ли вы реальные ограничения (не живёте в мире абстракций)
  • Можете ли вы обосновать выбор технологии с точки зрения стоимости
  • Знаете ли you, как физическая инфраструктура влияет на архитектуру

Как естественно внедрить в разговор:

“Для базы данных я выбираю SSD, потому что latency в 100 мкс против 5 мс у HDD - критично для нашего SLA в 200 мс.”

“Шардирование по chat_id означает, что hot chats создадут hotspot на одном шарде. В реальности это означает, что один сервер в стойке будет нагружен сильнее остальных.”

“Multi-region replication добавляет latency 50-200 мс между континентами. Поэтому мы используем eventual consistency для межрегиональной синхронизации, а strong consistency - внутри региона.”

“Хранение 14.6 ПБ медиа в S3 обойдётся в ~$336 000/мес. Если использовать SSD - это был бы astronomical cost. Поэтому hot медиа в CDN, а архив - в S3 Glacier.”


Разбор: URL Shortener

Этот разбор демонстрирует контраст с WhatsApp. Если WhatsApp - write-heavy система реального времени, то URL Shortener - read-heavy система с простой архитектурой и другими trade-off’ами.

Фаза 1: Требования

Функциональные:

  • Создание короткого alias для длинного URL
  • Перенаправление по короткому alias на оригинальный URL
  • Кастомные alias (опционально)
  • Срок действия ссылки (опционально)

Нефункциональные:

  • Latency: менее 100 мс на перенаправление
  • Доступность: 99.9%
  • Масштаб: 100 миллионов новых URL в месяц, 10 миллиардов перенаправлений в месяц

Info

Контраст с WhatsApp: URL Shortener создаёт мало данных (100M/мес), но читает много (10B/мес). WhatsApp создаёт много данных (2B/день) и читает много (20B/день), но соотношение read/write ближе к 10:1.


Фаза 2: Оценка масштаба

Новых URL в месяц: 100 000 000
Write QPS: 100M ÷ (30 × 86400) ≈ 40

Перенаправлений в месяц: 10 000 000 000
Read QPS: 10B ÷ (30 × 86400) ≈ 4 000

Средний размер URL: 500 байт
Хранилище в месяц: 100M × 500B = 50 ГБ
Хранилище в год: ~600 ГБ

Important

Контраст с WhatsApp: Write QPS всего 40 (против 23 000), read QPS 4 000 (против 230 000). Но соотношение read/write = 100:1 (против 10:1 у WhatsApp). Это кардинально меняет архитектуру.


Фаза 3: Высокоуровневый дизайн

Архитектура:

┌─────────┐     ┌───────────────┐     ┌─────────────┐     ┌──────────┐
│ Client  │────→│ Load Balancer │────→│ App Server  │────→│ Cache    │
└─────────┘     └───────────────┘     └─────────────┘     │ (Redis)  │
                                                          └────┬─────┘
                                                               │
                                                               ↓
                                                          ┌──────────┐
                                                          │ Database │
                                                          │ (SQL or  │
                                                          │  NoSQL)  │
                                                          └──────────┘

API:

MethodEndpointОписание
POST/shortenСоздать короткий URL
GET/{short_code}Перенаправить на оригинальный URL

Модель данных:

url_mappings
  - short_code (PK, строка 7 символов)
  - original_url (строка, индексировано)
  - created_at
  - expires_at (опционально)
  - click_count

Фаза 4: Углубление

Тема 1: Генерация коротких ссылок

Три подхода:

ПодходПринципПлюсыМинусы
Hash-basedMD5/SHA-256 от URL, первые 7 символовДетерминировано, одинаковый URL → одинаковый short codeКоллизии, предсказуемо
Base62 encodingАвтоинкремент ID в base62 (0-9, a-z, A-Z)Просто, компактноПредсказуемо, можно угадать следующую ссылку
Random stringСлучайные 7 символов base62Непредсказуемо, 3.5 триллиона комбинацийНужна проверка коллизий

Important

Выбор: Random string 7 символов base62 = 62^7 ≈ 3.5 триллиона комбинаций. При 100M URL/мес коллизии практически невозможны. Это самый популярный подход в production.

Контраст с WhatsApp:

  • WhatsApp: сообщения уникальны по времени + sender (нет коллизий)
  • URL Shortener: короткие коды должны быть уникальны (нужна проверка коллизий)

Тема 2: Оптимизация чтения

Кэш-first архитектура:

  • Redis с TTL (например, 24 часа для популярных ссылок)
  • Cache hit ratio: 95%+
  • Cache miss: запрос в БД, запись в кэш

Почему это работает:

  • 95%+ перенаправлений идут на популярные ссылки
  • Redis даёт latency < 1 мс
  • БД используется только для 5% запросов

Info

Контраст с WhatsApp: WhatsApp тоже использует кэш (Redis для последних сообщений), но там кэш менее эффективен, потому что каждый пользователь читает разные сообщения. URL Shortener имеет высокую локальность популярных ссылок.

Тема 3: Выбор базы данных

Trade-off SQL vs NoSQL:

АспектSQL (PostgreSQL)NoSQL (Cassandra)
КонсистентностьACID, strong consistencyEventual consistency
МасштабированиеVertical + read replicasHorizontal шардирование
ЗапросыСложные запросы, JOIN’ыПростые ключ-значение
Подходит для< 10K QPS> 10K QPS

Ключевой вопрос:

“URL Shortener требует strong consistency - мы не можем позволить двум разным URL иметь одинаковый short code. Это аргумент за SQL. Но с 4000 read QPS и кэшированием мы можем использовать PostgreSQL с read replicas.”

Important

Выбор: PostgreSQL с read replicas + Redis кэш. При необходимости масштабирования - шардирование по short_code prefix.

Контраст с WhatsApp:

  • URL Shortener: strong consistency критична (нет дубликатов short codes)
  • WhatsApp: eventual consistency допустима (сообщения дойдут через секунду)
  • URL Shortener: read-heavy (100:1), оптимизация на чтение
  • WhatsApp: write-heavy (10:1), оптимизация на запись

Фаза 5: Завершение

Аналитика:

  • Отслеживание кликов (click_count в БД)
  • Географическое распределение кликов
  • Популярные ссылки

Очистка:

  • Удаление просроченных ссылок
  • Архивация старых записей
  • Компактный формат для архива

Rate limiting:

  • Ограничение создания ссылок с одного IP
  • Защита от злоупотреблений

Сравнительная таблица: WhatsApp vs URL Shortener

АспектWhatsAppURL Shortener
Тип нагрузкиWrite-heavy (10:1)Read-heavy (100:1)
КонсистентностьEventual consistency допустимаStrong consistency обязательна
СложностьВысокая (real-time, sync, media)Низкая (простое перенаправление)
Ключевой компонентWebSocket, Message QueueКэш (Redis)
База данныхNoSQL (шардирование)SQL (ACID)
Latency требование< 200 мс< 100 мс
Соотношение R/W QPS230K / 23K4K / 40

Summary

Эти два примера показывают, как одинаковый пятифазный фреймворк применяется к совершенно разным системам. WhatsApp требует сложной архитектуры реального времени. URL Shortener - простой, но требует оптимизации чтения и strong consistency. На интервью важно показать, что вы понимаете специфику задачи и адаптируете архитектуру под неё.


Подготовка к интервью

Чек-лист подготовки

Основные темы для повторения

  • Масштабирование

    • Horizontal vs vertical scaling
    • Шардирование (sharding) - по какому ключу, какие проблемы
    • Репликация - master-slave, master-master, quorum
    • CAP теорема - когда выбирать consistency, когда availability
  • Базы данных

    • SQL vs NoSQL - trade-off’ы, когда что использовать
    • Индексы - B-tree, hash, inverted
    • Транзакции - ACID, isolation levels
    • Нормализация vs денормализация
  • Кэширование

    • Cache aside, read-through, write-through, write-behind
    • Cache eviction policies - LRU, LFU, TTL
    • Cache invalidation strategies
    • Distributed caching - Redis, Memcached
  • Сообщения и очереди

    • Message brokers - Kafka, RabbitMQ, SQS
    • Publish-subscribe vs point-to-point
    • Гарантии доставки - at-most-once, at-least-once, exactly-once
    • Backpressure и circuit breaker
  • Сети

    • HTTP/1.1 vs HTTP/2 vs HTTP/3
    • WebSocket vs Server-Sent Events vs Long Polling
    • Load balancing - round-robin, least connections, consistent hashing
    • CDN - как работает, когда использовать
  • Безопасность

    • HTTPS / TLS - как работает handshake
    • OAuth 2.0 / JWT - аутентификация и авторизация
    • SQL injection, XSS, CSRF - защита
    • Rate limiting - token bucket, leaky bucket
  • Микросервисы

    • Service discovery - Consul, Eureka, K8s DNS
    • API Gateway - routing, rate limiting, auth
    • Inter-service communication - REST, gRPC, messaging
    • Service mesh - Istio, Linkerd
  • Наблюдаемость

    • Метрики - latency, throughput, error rate
    • Логирование - структурированные логи, уровни
    • Трейсинг - distributed tracing, Jaeger, Zipkin
    • Alerting - когда и как оповещать

Практические задачи

Потренируйтесь на этих системах:

  1. WhatsApp / Telegram - мессенджер (write-heavy, real-time)
  2. URL Shortener - сервис коротких ссылок (read-heavy, simple)
  3. Twitter / News Feed - лента новостей (read-heavy, fan-out)
  4. Uber / Lyft - сервис заказа такси (real-time, geospatial)
  5. Netflix / YouTube - видеостриминг (bandwidth-heavy, CDN)
  6. Amazon / E-commerce - интернет-магазин (transactions, search)
  7. Google Docs - совместное редактирование (real-time collaboration)
  8. Rate Limiter - ограничение запросов (distributed, accurate)

Info

Для каждой задачи пройдите все 5 фаз: требования → оценка → HLD → deep dive → wrap-up. Потратьте 45-60 минут, как на реальном интервью.

Ресурсы

Книги:

  • “Designing Data-Intensive Applications” by Martin Kleppmann (DDIA) - обязательна
  • “System Design Interview” by Alex Xu - структура интервью
  • “Grokking the System Design Interview” - краткий обзор

Веб-сайты:

  • System Design Primer (GitHub) - отличная отправная точка
  • ByteByteGo (YouTube) - визуальные объяснения
  • DesignGurus.io - структурированные курсы

Практика:

  • Pramp - бесплатные mock interviews
  • Interviewing.io - mock interviews с инженерами
  • Практикуйтесь с другом - один интервьюер, другой кандидат

Стратегия mock interview

  1. Найдите партнёра - друг, коллега или сервис вроде Pramp
  2. Выберите задачу - из списка выше или придумайте сами
  3. Установите таймер - 60 минут, без перерывов
  4. Делайте заметки - что пошло хорошо, что улучшить
  5. Получите feedback - попросите партнёра оценить по 4 компетенциям

Типичные ошибки

Ошибка 1: Начать решать без уточнения требований

Почему это проблема: Вы проектируете систему для неправильного масштаба или упускаете критичные требования. Интервьюер специально даёт минимум информации, чтобы проверить, зададите ли вы вопросы.

Как избежать: Всегда начинайте с 3-5 уточняющих вопросов. Даже если требования кажутся очевидными, уточните масштаб и приоритеты.

Что сказать:

“Прежде чем начать проектировать, хочу уточнить несколько моментов. Для скольких пользователей мы проектируем? Какие функции обязательны? Есть ли ограничения по latency?”


Ошибка 2: Игнорировать нефункциональные требования

Почему это проблема: Доступность 99.9% и 99.999% - это разные архитектуры. eventual consistency и strong consistency - разные решения. Без этих требований вы не можете обосновать выбор технологий.

Как избежать: Явно спросите про:

  • Availability (99.9%, 99.99%, 99.999%)
  • Consistency (strong, eventual, causal)
  • Latency (p50, p95, p99)
  • Throughput (QPS, bandwidth)

Ошибка 3: Переусложнять с первого шага

Почему это проблема: Сложная архитектура из 15 компонентов трудно объяснить и отлаживать. Интервьюер оценивает процесс мышления, а не количество компонентов. Переусложнение показывает неумение приоритизировать.

Как избежать: Начинайте с 3-5 компонентов. Усложняйте только там, где это обосновано. Правило: “Простое решение, которое работает, лучше сложного, которое тоже работает.”


Ошибка 4: Не обсуждать trade-off’ы

Почему это проблема: Каждое решение имеет цену. Если вы не обсуждаете альтернативы, интервьюер не видит глубины вашего понимания. “Я выбираю NoSQL” без объяснения почему - недостаточно.

Как избежать: Для каждого ключевого решения предлагайте 2-3 альтернативы:

“Для хранения можно использовать PostgreSQL или Cassandra. PostgreSQL даёт ACID и сложные запросы, но сложнее масштабировать. Cassandra легко шардировать, но eventual consistency может быть проблемой. Я выбираю PostgreSQL, потому что strong consistency критична для этой задачи.”


Ошибка 5: Молчать или думать про себя

Почему это проблема: Интервьюер не видит ваш процесс мышления. Вы можете прийти к правильному ответу, но не получить credit за путь. Молчание на 5 минут - красный флаг.

Как избежать: Думайте вслух. Объясняйте каждый шаг. Рисуйте на доске или в редакторе. Даже если вы не уверены, скажите: “Я думаю над этим. Вот варианты, которые рассматриваю…”


Ошибка 6: Не оценивать масштаб

Почему это проблема: Без расчётов вы не можете обосновать выбор технологий. SQL может быть нормально для 1000 пользователей, но не для 100 миллионов. Оценка масштаба - основа всех последующих решений.

Как избежать: Всегда делайте back-of-the-envelope расчёты. Показывайте их на доске. Объясняйте assumptions.


Ошибка 7: Забывать про мониторинг и отказы

Почему это проблема: Production система без мониторинга - это чёрный ящик. Без плана отказов - это система, которая упадёт при первой проблеме. Интервьюер хочет видеть, что вы думаете о production.

Как избежать: Завершайте интервью обсуждением:

  • Какие метрики мониторить (latency, error rate, throughput)
  • Какие алерты настроить
  • Что делать при отказе БД, сервера, датацентра

Ошибка 8: Защищать ошибочное решение

Почему это проблема: Интервьюер может указывать на реальные проблемы. Защита “до последнего” показывает негибкость и неумение слушать feedback.

Как избежать: Будьте открыты к корректировкам:

“Вы правы, этот подход создаёт bottleneck при пиковой нагрузке. Давайте пересмотрим - вместо одного master’а используем шардирование.”


Ошибка 9: Не спрашивать направления у интервьюера

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

Как избежать: Спрашивайте:

“В какую часть системы стоит углубиться?” “Что для вас наиболее интересно в этом дизайне?”


План подготовки на 2 недели

Неделя 1: Теория

ДеньТемаДействие
1МасштабированиеПрочитать главу о масштабировании в DDIA. Повторить CAP теорему.
2Базы данныхПрочитать про SQL vs NoSQL, индексы, шардирование.
3КэшированиеИзучить стратегии кэширования, eviction policies.
4СообщенияИзучить Kafka, RabbitMQ, гарантии доставки.
5СетиПовторить HTTP/2, WebSocket, load balancing, CDN.
6БезопасностьПовторить TLS, OAuth, JWT, основные атаки.
7МикросервисыИзучить service discovery, API gateway, service mesh.

Неделя 2: Практика

ДеньЗадачаДействие
8WhatsAppПройти все 5 фаз самостоятельно, записать на видео.
9URL ShortenerПройти все 5 фаз, сравнить с WhatsApp.
10TwitterПотренироваться на feed системе.
11UberПотренироваться на geospatial задаче.
12Mock interview 1С другом или на Pramp. Получить feedback.
13NetflixПотренироваться на стриминговой системе.
14Mock interview 2С другом или на Pramp. Сравнить прогресс.

Important

Ключ к успеху - регулярная практика. Одно интервью в неделю лучше, чем 10 интервью за один день перед собеседованием. Процесс мышления вырабатывается через повторение.


Заключение

System Design интервью - это навык, который развивается через практику. Пятифазный фреймворк (требования → оценка → HLD → deep dive → wrap-up) даёт структуру, в рамках которой вы можете демонстрировать своё мышление. Два разбора в этой заметке - WhatsApp и URL Shortener - показывают, как один и тот же фреймворк применяется к разным типам систем с разными trade-off’ами.

Ключевые принципы, которые стоит запомнить:

  1. Начинайте с вопросов, а не с решения. Уточнение требований - самый важный первый шаг.

  2. Показывайте расчёты. Back-of-the-envelope оценки демонстрируют понимание масштаба.

  3. Обсуждайте trade-off’ы. Для каждого решения предлагайте альтернативы и объясняйте выбор.

  4. Думайте вслух. Интервьюер оценивает процесс, а не только результат.

  5. Завершайте обсуждением production. Мониторинг, отказы, масштабирование - всё это показывает зрелость мышления.

Полезные ссылки

Important

Практика важнее теории. Потратьте 45-60 минут на полный проход хотя бы для трёх разных систем. Запишите себя на видео или попросите друга сыграть роль интервьюера. Каждое практическое интервью делает вас увереннее.