Адриан из JavaScript Mastery: «Ваше приложение сломается именно в таком порядке»

JavaScript Mastery 65 тыс. 38 мин 5 мин 04.09.2026
Главное

Сегодня создание полноценного приложения — фронтенда, бэкенда и базы данных — стало доступнее благодаря инструментам ИИ, но настоящая проверка навыков инженера начинается в момент роста популярности продукта. Автор канала JavaScript Mastery Адриан утверждает, что построить приложение никогда не было самой сложной частью; настоящий вызов — это проектирование систем (System Design), когда один сервер перестает справляться с нагрузкой. В этом материале рассматривается путь эволюции архитектуры: от простейшего сервера до распределенных баз данных, где каждый новый слой добавляется только тогда, когда предыдущий намеренно доводится до критической точки.

🚀 Начальная точка: Один сервер для тысяч пользователей 1:39

Большинство современных приложений начинают свой путь с простейшей схемы: один сервер, исполняющий программный код, и одна база данных для хранения информации. По словам Адриана, такой конфигурации достаточно не для десятков, а для тысяч активных пользователей . Многие проекты никогда не перерастают этот этап, и в этом нет ничего плохого — это стабильная и понятная архитектура.

Однако проблемы начинаются при резких всплесках трафика, например, во время распродажи билетов на концерт или крупного медийного события. Когда тысячи людей одновременно пытаются совершить действие, сервер начинает «тонуть»: запросы накапливаются в очереди, время ожидания растет, и в итоге пользователи получают ошибки по таймауту . В этот момент разработчик встает перед выбором между двумя стратегиями масштабирования:

⚖️ Балансировка нагрузки и проблема «состояния» 2:20

Как только в системе появляется более одного сервера, возникает вопрос: как распределять запросы между ними? Для этого в архитектуру вводится Load Balancer (балансировщик нагрузки). Он выступает посредником, который принимает входящий трафик и перенаправляет его на менее занятый сервер . В качестве классического примера инструмента для этих целей автор называет NGINX, хотя платформы вроде Vercel или Railway предоставляют встроенную балансировку «из коробки» .

Однако введение балансировщика порождает новую проблему — проблему управления сессиями. Адриан описывает сценарий «случайного разлогина» :

  1. Пользователь авторизуется на Сервере А. Сервер сохраняет заметку о входе в своей оперативной памяти.
  2. При следующем клике балансировщик отправляет запрос на Сервер Б.
  3. Сервер Б «не знает» пользователя, так как его оперативная память пуста, и принудительно просит войти снова .

Решением становится переход к Stateless-серверам (серверам без сохранения состояния). Ни один сервер не должен хранить секреты о пользователе в своей локальной памяти. Все данные о сессиях выносятся в общее хранилище, доступное всем серверам системы. Чаще всего для этих целей используется Redis — высокоскоростное хранилище в оперативной памяти .

🗄️ База данных: пулы соединений и репликация 12:22

Даже если серверная часть масштабирована, общая база данных (БД) может стать узким местом. Автор выделяет две основные проблемы БД. Первая — лимит открытых соединений. Каждое соединение потребляет память, и их количество часто ограничено сотнями или даже десятками на недорогих тарифах . Ситуация усугубляется при использовании Serverless-решений (например, на Vercel), где резкий всплеск трафика может мгновенно создать сотни новых копий функций, каждая из которых попытается открыть свое соединение и «уронит» базу данными об ошибке подключения .

Для решения этой проблемы используется Connection Pooling (пул соединений) — например, инструмент PG bouncer для Postgres. Он поддерживает стабильное небольшое количество открытых линий к БД, которыми серверы «делятся» друг с другом .

Вторая проблема — исчерпание физической мощности одного устройства. Поскольку в большинстве приложений (таких как TikTok или соцсети) операций чтения в сотни раз больше, чем операций записи, Адриан предлагает использовать Read Replicas (реплики для чтения) :

Плата за такую скорость — Replication Lag (задержка репликации). Изменения доходят до реплик не мгновенно, и пользователь может не увидеть свой только что опубликованный пост в течение доли секунды . Автор подчеркивает: инженер должен сам решать, где допустима такая микро-задержка, а где (как в случае с балансом банковского счета) чтение должно идти только из основного источника .

⚡ Кэширование и оптимизация ресурсов 20:31

Некоторые запросы к базе данных обходятся слишком дорого, чтобы выполнять их постоянно. В качестве примера приводится расчет количества подписчиков у популярного блогера: базе приходится пересчитывать миллионы строк каждый раз, когда кто-то открывает профиль . Чтобы избежать этой бессмысленной траты ресурсов, используется кэширование.

Результат вычисления сохраняется в быстром хранилище (снова Redis). Следующий пользователь получает уже готовое число практически мгновенно . Главная сложность здесь — инвалидация кэша, то есть понимание того, когда сохраненный ответ устарел и его нужно удалить . Адриан отмечает, что это скорее продуктовое решение, чем техническое: приемлемо ли показывать старое число подписчиков в течение 30 секунд? Для соцсети — да, для банковских операций — нет .

✉️ Очереди задач и фоновые процессы 25:09

Иногда приложение кажется медленным из-за задач, которые сервер пытается выполнить прямо во время ответа пользователю. Например, при регистрации система может отправлять письмо с подтверждением, собирать аналитику и подготавливать данные аккаунта . Если внешний сервис рассылки писем работает медленно или временно недоступен, регистрация пользователя «повиснет» или завершится ошибкой .

Решение заключается в разделении работы:

  1. Сервер создает запись в БД и немедленно отвечает пользователю: «Готово!».
  2. Тяжелая задача (отправка письма) записывается в Queue (очередь).
  3. Отдельный процесс, называемый Worker (воркер), постепенно забирает задачи из очереди и выполняет их в фоновом режиме .

Для реализации очередей в экосистеме JavaScript часто используется библиотека BullMQ, работающая на базе Redis .

💎 Шардирование: когда данных слишком много 30:03

Когда объем данных становится настолько огромным, что они физически не помещаются на один диск самого мощного сервера, применяется Sharding (шардирование). Это процесс разделения одной огромной таблицы на части (шарды), распределенные по разным базам данных .

Чтобы система знала, в какой шарде искать конкретного пользователя, используется фиксированное правило, например, деление ID пользователя на количество шардов и использование остатка от деления . Однако шардирование имеет высокую цену:

Адриан приводит в пример компанию Notion, которая успешно перешла на шардированную архитектуру, имея более 200 миллиардов строк данных, сохранив при этом работоспособность продукта во время миграции .

В заключение автор подчеркивает, что проектирование систем — это не просто рисование «коробочек» на схеме, а искусство поиска компромиссов между скоростью, стоимостью и точностью данных .

💬 Цитаты

«В программировании есть только две сложные вещи: инвалидация кэша и придумывание названий.»

Адриан (цитируя старую инженерную шутку) 23:13

«ИИ с удовольствием напишет код для кэширования за вас, но он не примет решение за продукт.»

👥 Спикер
🔗 Упомянутые сайты и проекты
📖 Термины
Load Balancer
Устройство или программа, распределяющая входящий сетевой трафик между группой серверов.
Stateless
Архитектура сервера, при которой он не хранит информацию о сессии пользователя между запросами в своей локальной памяти.
Redis
Высокопроизводительное хранилище данных в оперативной памяти, используемое как база данных, кэш и брокер сообщений.
Sharding
Метод горизонтального масштабирования базы данных путем разделения одной таблицы на части между разными серверами.
Worker
Отдельный процесс или сервис, предназначенный для выполнения фоновых задач из очереди.
📊 Цифры
🗓 Хронология
  1. 10:00 AM Типичное время старта продаж билетов, вызывающее пиковую нагрузку на серверы.
  2. 2026-09-06 Дата публикации/анализа материала по архитектуре систем.
⚖️ Другая сторона
Инженерия System Design Redis Sharding Load Balancing JavaScript Mastery