Секция мобильного system design есть у крупных компаний для middle+ и senior: «спроектируйте клиент ленты, мессенджера, такси». От бэкенд-секции она отличается фокусом: не шардирование баз, а клиент в ненадёжной сети с ограниченными памятью, батареей и трафиком.
План на 45-60 минут
- Требования (5-7 минут). Какие функции в рамках, нужен ли офлайн, платформы, масштаб, что важнее: свежесть, скорость, трафик. Допущения проговорить вслух.
- Оценка объёмов. Размер страницы, картинки, кеш. Например, 20 постов по 3 картинки по 100 КБ это 6 МБ на страницу, значит превью нужного размера обязательны.
- API и протоколы. Эндпоинты, курсорная пагинация, реалтайм-канал, формат ошибок, идемпотентность.
- Данные на клиенте. Локальная база как источник правды, что кешировать и сколько.
- Архитектура клиента. Слои, модули, потоки данных, схема.
- Глубина. Офлайн и синхронизация, кеш медиа, производительность списков, безопасность, наблюдаемость.
- Компромиссы и что изменится при росте.
Протоколы
| Задача | Выбор |
|---|---|
| CRUD, большинство экранов | REST (кешируется HTTP) |
| Экран собирает много сущностей | GraphQL или агрегирующий эндпоинт |
| Чат, двусторонний реалтайм | WebSocket на переднем плане |
| Поток событий от сервера | SSE |
| Фон | push + синхронизация при открытии |
| Большие файлы | загрузка частями по presigned URL |
Типовые блоки решений
Лента. Курсорная пагинация, prefetch за 1-2 экрана, дедупликация по id, показ из кеша сразу, новые посты плашкой, а не прыжком списка, картинки нужного размера, автоплей только видимого видео.
Мессенджер. WebSocket пока приложение открыто, push в фоне, догрузка пропущенного по серверному порядковому номеру. Клиентский UUID сообщения для идемпотентности, порядок по серверным номерам (часам устройств не доверяем), outbox для офлайн-отправки, агрегированные статусы прочтения в больших группах.
Загрузка медиа. Сжатие и перекодирование, загрузка частями (S3 multipart, tus) напрямую в хранилище по presigned URL, фоновая сессия или WorkManager, повтор отдельных частей, продолжение после перезапуска, дедупликация по хешу.
Реалтайм на карте. Адаптивная частота координат, пакетная отправка, интерполяция маркера на клиенте, машина состояний заказа, восстановление после обрыва.
Платежи и деньги. Идемпотентные операции с клиентским id, отдельное состояние «неизвестно, проверяем», никаких оптимистичных успехов, сервер как источник правды.
Офлайн-редактирование. Локальная база, outbox, дельта-синхронизация с надгробиями, версии записей и слияние по полям, CRDT для текста.
Нефункциональные требования
- Производительность: время до контента, плавность, холодный старт.
- Ресурсы: память, батарея, трафик, размер приложения.
- Надёжность: обрывы сети, выгрузка процесса, повторы.
- Безопасность: хранение токенов, TLS, приватность в логах.
- Наблюдаемость: крэши, метрики, логирование без персональных данных.
- Совместимость: старые версии клиента, server-driven части.
Компромиссы, которые стоит назвать
Свежесть против скорости и трафика, офлайн против сложности синхронизации, реалтайм против батареи, server-driven UI против нативности и совместимости, безопасность против удобства.
Частые ошибки
- Начать с классов без требований.
- Проектировать бэкенд вместо клиента (если не просили).
- Забыть про офлайн, обрывы и выгрузку процесса.
- Не связать решения с цифрами и метриками.
- Молчать: интервьюер оценивает ход мысли.
Что спросят на собесе
- Спроектируйте ленту, мессенджер, загрузку видео, такси, корзину маркетплейса.
- Как клиент получает обновления в реальном времени?
- Что произойдёт при обрыве сети в середине операции?
- Как вы выберете между REST, GraphQL и WebSocket?
- Какие компромиссы вы приняли и почему?