Если вы использовали joho/godotenv в Go, скорее всего делали так в начале main.go.
Работает, но есть более чистый однострочник — трюк с /joho/godotenv/autoload.
Пустой идентификатор
- Ноль бойлерплейта
- Загружается раньше всего: init() вызывается до main(), поэтому переменные окружения готовы даже для инициализации переменных на уровне пакета
- Подходит для скриптов, демо и небольших утилит
НО НЕ ИСПОЛЬЗУЙТЕ ЭТО В ПРОДАКШЕНЕ:
- Потому что ошибки тихо игнорируются: autoload вызывает godotenv.Load() и не обрабатывает возвращаемую ошибку
- Нет контроля порядка и путей: нельзя загрузить .env.local или .env.production
👉 @BackendPortal
Работает, но есть более чистый однострочник — трюк с /joho/godotenv/autoload.
Пустой идентификатор
_ говорит Go просто выполнить функцию init() из этого пакета (autoload).- Ноль бойлерплейта
- Загружается раньше всего: init() вызывается до main(), поэтому переменные окружения готовы даже для инициализации переменных на уровне пакета
- Подходит для скриптов, демо и небольших утилит
НО НЕ ИСПОЛЬЗУЙТЕ ЭТО В ПРОДАКШЕНЕ:
- Потому что ошибки тихо игнорируются: autoload вызывает godotenv.Load() и не обрабатывает возвращаемую ошибку
- Нет контроля порядка и путей: нельзя загрузить .env.local или .env.production
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Система для блогов с открытым исходным кодом и разделёнными фронтендом и бэкендом: Go-бэкенд в паре с React-фронтендом, готовая к использованию из коробки и поддерживающая развёртывание через Docker.
https://github.com/domye/Solace
Solace — это фулстек-система для блогов. Бэкенд построен на Go + Gin + GORM + PostgreSQL, фронтенд — на React 18 + TypeScript + Tailwind CSS.
Поддерживаются редактирование Markdown, категории и теги, фотоальбомы, полнотекстовый поиск, вход по JWT и документация Swagger. Код организован по слоям в духе clean architecture, поэтому проект можно запускать локально или разворачивать в один клик через Docker Compose.
👉 @BackendPortal
https://github.com/domye/Solace
Solace — это фулстек-система для блогов. Бэкенд построен на Go + Gin + GORM + PostgreSQL, фронтенд — на React 18 + TypeScript + Tailwind CSS.
Поддерживаются редактирование Markdown, категории и теги, фотоальбомы, полнотекстовый поиск, вход по JWT и документация Swagger. Код организован по слоям в духе clean architecture, поэтому проект можно запускать локально или разворачивать в один клик через Docker Compose.
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - domye/Solace: Solace - 基于 Go + React + TypeScript + PostgreSQL 的全栈博客系统。支持 Markdown 编辑、相册管理、深色模式、SEO 优化、Docker 部署。采用整洁…
Solace - 基于 Go + React + TypeScript + PostgreSQL 的全栈博客系统。支持 Markdown 编辑、相册管理、深色模式、SEO 优化、Docker 部署。采用整洁架构,适合个人博客、技术博客、开发者作品集。MIT 开源,生产就绪 - domye/Solace
❤3
This media is not supported in your browser
VIEW IN TELEGRAM
Liam ERD
Это опенсорсный инструмент, который мгновенно генерирует красивые, интерактивные ER-диаграммы из существующих баз данных
Просто загружаете схему, и получаете понятные визуализации, где можно удобно смотреть связи, приближать, фильтровать и быстро разбираться даже с суперсложными структурами.
И всё это бесплатно и без необходимости регистрации. Инструкция на GitHub, ссылка на сервис.
👉 @BackendPortal
Это опенсорсный инструмент, который мгновенно генерирует красивые, интерактивные ER-диаграммы из существующих баз данных
Просто загружаете схему, и получаете понятные визуализации, где можно удобно смотреть связи, приближать, фильтровать и быстро разбираться даже с суперсложными структурами.
И всё это бесплатно и без необходимости регистрации. Инструкция на GitHub, ссылка на сервис.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Как понять, что твоя стратегия кеширования правильная?
Ключевая метрика — процент запросов, когда данные находятся в кеше.
Это называется коэффициент попаданий в кеш и показывает, как часто ты можешь переиспользовать закешированный объект.
Вот как замаксить этот коэффициент:
I. Размер пространства ключей
Единственный способ найти элемент в кеше — точно совпасть по ключу.
Чем меньше возможных ключей, тем эффективнее кеш.
Всегда думай, как уменьшить количество возможных ключей.
II. Размер кеша и элементов
Сколько объектов ты можешь хранить в кеше, зависит от их среднего размера и размера самого кеша.
Когда кеш заполнен, приходится вытеснять старые элементы перед добавлением новых.
Это снижает коэффициент попаданий, потому что элементы удаляются даже если могли бы удовлетворить будущие запросы.
Значит, чем больше элементов помещается в кеш, тем выше будет коэффициент попаданий.
III. Долговечность
Во многих случаях можно кешировать объекты на предопределённое время, так называемый Time to Live, TTL.
В других случаях ты не можешь рисковать устаревшими данными и должен инвалидировать объекты в кеше.
В общем, чем дольше ты можешь держать элементы в кеше, тем выше шанс их переиспользовать.
Большинство кейсов, хорошо подходящих для кеширования, имеют высокий ratio чтений к записям.
Потому что закешированные элементы можно создать один раз и хранить длительное время, пока они не истекут или не станут невалидными.
С другой стороны, кейсы с частыми изменениями данных могут сделать кеш бесполезным, потому что элементы успевают устареть до следующего использования.
👉 @BackendPortal
Ключевая метрика — процент запросов, когда данные находятся в кеше.
Это называется коэффициент попаданий в кеш и показывает, как часто ты можешь переиспользовать закешированный объект.
Вот как замаксить этот коэффициент:
I. Размер пространства ключей
Единственный способ найти элемент в кеше — точно совпасть по ключу.
Чем меньше возможных ключей, тем эффективнее кеш.
Всегда думай, как уменьшить количество возможных ключей.
II. Размер кеша и элементов
Сколько объектов ты можешь хранить в кеше, зависит от их среднего размера и размера самого кеша.
Когда кеш заполнен, приходится вытеснять старые элементы перед добавлением новых.
Это снижает коэффициент попаданий, потому что элементы удаляются даже если могли бы удовлетворить будущие запросы.
Значит, чем больше элементов помещается в кеш, тем выше будет коэффициент попаданий.
III. Долговечность
Во многих случаях можно кешировать объекты на предопределённое время, так называемый Time to Live, TTL.
В других случаях ты не можешь рисковать устаревшими данными и должен инвалидировать объекты в кеше.
В общем, чем дольше ты можешь держать элементы в кеше, тем выше шанс их переиспользовать.
Большинство кейсов, хорошо подходящих для кеширования, имеют высокий ratio чтений к записям.
Потому что закешированные элементы можно создать один раз и хранить длительное время, пока они не истекут или не станут невалидными.
С другой стороны, кейсы с частыми изменениями данных могут сделать кеш бесполезным, потому что элементы успевают устареть до следующего использования.
Please open Telegram to view this post
VIEW IN TELEGRAM
💊2
Примеры Dockerfile для frontend и backend приложений
🟡 Frontend Dockerfile: Использует node:18-alpine, устанавливает зависимости и запускает приложение.
🟡 Backend Dockerfile: Использует python:3.11-slim-buster, устанавливает зависимости из requirements.txt и запускает
🟡 Команды для сборки образов: docker build -t frontend . и docker build -t backend .
🟡 Команды для запуска контейнеров: docker run -d --name frontend -p 8080:3000 frontend и docker run -d --name backend -p 8081:5000 backend.
Это базовый пример развертывания веб-приложения с фронтендом на Node.js и бэкендом на Python в Docker.
👉 @BackendPortal
app.py.Это базовый пример развертывания веб-приложения с фронтендом на Node.js и бэкендом на Python в Docker.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
Нашёл на GitHub интересный репозиторий — awesome-console-services, где собран список полезных консольных сервисов, доступных через HTTP, HTTPS и другие протоколы!
В этом репозитории можно найти утилиты для различных задач, таких как:
🟡 Узнать IP-адрес и геолокацию
🟡 Сократить URL
🟡 Отправить файл через консоль
🟡 Создать QR-код
🟡 Получить погоду, новости, курсы валют
🟡 Проверить онлайн-статус Twitch-канала
🟡 Сделать Whois-запрос и многое другое!
Попробуй сам: тык
👉 @BackendPortal
В этом репозитории можно найти утилиты для различных задач, таких как:
Попробуй сам: тык
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
У меня было два сервера с WebSocket.
Клиент 1 на сервере 1, клиент 2 на сервере 2, но оба в одной комнате.
Клиент 1 отправил сообщение.
Сервер 1 его получил.
Но сокет клиента 2 был на сервере 2.
Сервер 1 даже не знал о его существовании.
В итоге сообщение не дошло.
Это базовая проблема горизонтального масштабирования со состоянием. Стандартное решение — бекплейн: Redis pub/sub, Kafka, NATS.
Сервер 1 публикует → сервер 2, подписанный на бекплейн, получает сообщение и отправляет клиенту 2.
Но бекплейн не бесплатен. Появляются нюансы, о которых обычно не говорят.
Ломается порядок сообщений. Два сообщения с разных серверов могут прийти в разном порядке из-за микрозадержек.
Фикс — вводить порядковые номера. Но тогда нужен централизованный счётчик, снова Redis. Зависимости начинают накапливаться.
Растёт задержка. Сообщение теперь идёт отправитель → бекплейн → получатель. Дополнительный сетевой хоп на каждое сообщение.
Есть и менее очевидная проблема, которая всплыла в тестах.
Сначала использовал wildcard-подписку в NATS —
Сервер без пользователей в
Перешёл на подписки по комнатам — проблема исчезла.
Например: сервер 1 подписывается на
В итоге каждый сервер получает только те сообщения, где у него есть пользователи.
Бекплейн необходим для горизонтального масштабирования. Но рекомендации уровня «просто используй Redis» обычно не затрагивают последствия, которые появляются дальше.
👉 @BackendPortal
Клиент 1 на сервере 1, клиент 2 на сервере 2, но оба в одной комнате.
Клиент 1 отправил сообщение.
Сервер 1 его получил.
Но сокет клиента 2 был на сервере 2.
Сервер 1 даже не знал о его существовании.
В итоге сообщение не дошло.
Это базовая проблема горизонтального масштабирования со состоянием. Стандартное решение — бекплейн: Redis pub/sub, Kafka, NATS.
Сервер 1 публикует → сервер 2, подписанный на бекплейн, получает сообщение и отправляет клиенту 2.
Но бекплейн не бесплатен. Появляются нюансы, о которых обычно не говорят.
Ломается порядок сообщений. Два сообщения с разных серверов могут прийти в разном порядке из-за микрозадержек.
Фикс — вводить порядковые номера. Но тогда нужен централизованный счётчик, снова Redis. Зависимости начинают накапливаться.
Растёт задержка. Сообщение теперь идёт отправитель → бекплейн → получатель. Дополнительный сетевой хоп на каждое сообщение.
Есть и менее очевидная проблема, которая всплыла в тестах.
Сначала использовал wildcard-подписку в NATS —
chat.*. Каждый сервер получал все сообщения и фильтровал локально.Сервер без пользователей в
general всё равно обрабатывал каждое сообщение из general. Пустая нагрузка на CPU.Перешёл на подписки по комнатам — проблема исчезла.
Например: сервер 1 подписывается на
chat.general, chat.random и т.д. Сервер 2 аналогично.В итоге каждый сервер получает только те сообщения, где у него есть пользователи.
Бекплейн необходим для горизонтального масштабирования. Но рекомендации уровня «просто используй Redis» обычно не затрагивают последствия, которые появляются дальше.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
Отключение WebSocket-сервера на обслуживание выглядит простой задачей.
Но при 33 000 активных соединений просто «убить» процесс нельзя — все клиенты отвалятся одновременно, возникнет thundering herd и потеря данных.
Решение — graceful shutdown. Это базовый паттерн для состояния в проде.
Два шага.
Шаг 1 — дренаж сервера.
Убрать его из балансировщика. Новые соединения не принимаются, текущие продолжают жить.
Шаг 2 — сигнал клиентам.
Отправить всем подключённым сообщение «переподключитесь». Клиенты делают реконнект с джиттером на оставшиеся серверы.
Результат — нагрузка размазывается во времени.
Не 33 000 реконнектов в одну секунду, а распределение, например, на 30 секунд.
Результаты нагрузочного теста:
- Без graceful shutdown → 752 фейла реконнекта, P99 задержка 18 секунд
- С graceful shutdown → 0 фейлов, P99 < 3 секунд
Разница не в железе и не в инфраструктуре.
Решает порядок операций.
Сначала дренаж, потом сигнал клиентам, дальше джиттер.
Масштабирование вниз требует такой же дисциплины, как и масштабирование вверх.
👉 @BackendPortal
Но при 33 000 активных соединений просто «убить» процесс нельзя — все клиенты отвалятся одновременно, возникнет thundering herd и потеря данных.
Решение — graceful shutdown. Это базовый паттерн для состояния в проде.
Два шага.
Шаг 1 — дренаж сервера.
Убрать его из балансировщика. Новые соединения не принимаются, текущие продолжают жить.
Шаг 2 — сигнал клиентам.
Отправить всем подключённым сообщение «переподключитесь». Клиенты делают реконнект с джиттером на оставшиеся серверы.
Результат — нагрузка размазывается во времени.
Не 33 000 реконнектов в одну секунду, а распределение, например, на 30 секунд.
Результаты нагрузочного теста:
- Без graceful shutdown → 752 фейла реконнекта, P99 задержка 18 секунд
- С graceful shutdown → 0 фейлов, P99 < 3 секунд
Разница не в железе и не в инфраструктуре.
Решает порядок операций.
Сначала дренаж, потом сигнал клиентам, дальше джиттер.
Масштабирование вниз требует такой же дисциплины, как и масштабирование вверх.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8
В моём Discord-подобном проекте была комната
100 на сервере 1.
900 на сервере 2.
Кто-то отправляет сообщение в
Сервер 1 сериализует сообщение 100 раз, отправляет локальным пользователям и публикует его в NATS.
Сервер 2 получает сообщение из NATS, сериализует его 900 раз и отправляет локальным пользователям.
Сервер 2 делает в 9 раз больше работы. Даже при меньшем общем количестве соединений он упёрся в ЦПУ.
Балансировщик нагрузки сделал ситуацию хуже.
Я использовал
Из-за этого он продолжал отправлять новых пользователей на сервер 2, потому что по числу соединений тот выглядел «доступным». Больше пользователей, больше участников горячей комнаты, больше работы на рассылку.
Метрика, которая реально важна:
Это маршрутизация с учётом нагрузки сервера. Из коробки её нет в Nginx, Caddy или HAProxy.
Чтобы сделать это нормально, нужен либо кастомный балансировщик нагрузки, либо расширение существующего. Например, Nginx поддерживает Lua-скрипты.
Discord делает похожую штуку через маршрутизацию на стороне клиента: клиент сначала запрашивает метрики нагрузки серверов, затем подключается к наименее загруженному серверу.
Что для этого нужно:
- кастомная логика маршрутизации, которая понимает членство в комнатах;
- общее состояние: в каких комнатах есть пользователи на каких серверах;
- метрики в реальном времени от WebSocket-серверов в слой маршрутизации.
Обычные балансировщики видят соединения.
Они не видят комнаты, нагрузку от рассылки и давление на ЦПУ из-за сериализации.
Для небольшого масштаба
Но после определённого порога, если горячие комнаты распределены неравномерно, кастомная логика становится единственным нормальным вариантом.
👉 @BackendPortal
General на 1000 участников.100 на сервере 1.
900 на сервере 2.
Кто-то отправляет сообщение в
General.Сервер 1 сериализует сообщение 100 раз, отправляет локальным пользователям и публикует его в NATS.
Сервер 2 получает сообщение из NATS, сериализует его 900 раз и отправляет локальным пользователям.
Сервер 2 делает в 9 раз больше работы. Даже при меньшем общем количестве соединений он упёрся в ЦПУ.
Балансировщик нагрузки сделал ситуацию хуже.
Я использовал
least_conn — маршрутизацию на сервер с наименьшим количеством соединений.Из-за этого он продолжал отправлять новых пользователей на сервер 2, потому что по числу соединений тот выглядел «доступным». Больше пользователей, больше участников горячей комнаты, больше работы на рассылку.
Метрика, которая реально важна:
Нагрузка сервера = Σ (сообщений/сек в комнате × локальных пользователей в этой комнате)Это маршрутизация с учётом нагрузки сервера. Из коробки её нет в Nginx, Caddy или HAProxy.
Чтобы сделать это нормально, нужен либо кастомный балансировщик нагрузки, либо расширение существующего. Например, Nginx поддерживает Lua-скрипты.
Discord делает похожую штуку через маршрутизацию на стороне клиента: клиент сначала запрашивает метрики нагрузки серверов, затем подключается к наименее загруженному серверу.
Что для этого нужно:
- кастомная логика маршрутизации, которая понимает членство в комнатах;
- общее состояние: в каких комнатах есть пользователи на каких серверах;
- метрики в реальном времени от WebSocket-серверов в слой маршрутизации.
Обычные балансировщики видят соединения.
Они не видят комнаты, нагрузку от рассылки и давление на ЦПУ из-за сериализации.
Для небольшого масштаба
round robin неожиданно долго работает нормально.Но после определённого порога, если горячие комнаты распределены неравномерно, кастомная логика становится единственным нормальным вариантом.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
График объясняет событийно-ориентированную архитектуру (EDA). Он показывает, как системы могут реагировать на события, обрабатывая их асинхронно.
🟣 Производители создают события, потребители на них реагируют.
🟣 EDA улучшает масштабируемость и разделение зависимостей.
🟣 События передаются через шины или потоки.
🟣 Минусы: сложность в обработке ошибок и порядке событий.
Это подход, который часто используется в высоконагруженных системах, например, в e-commerce или финансовых сервисах.
👉 @BackendPortal
Это подход, который часто используется в высоконагруженных системах, например, в e-commerce или финансовых сервисах.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
image_2026-04-27_07-42-58.png
641.4 KB
Большинство разработчиков думают, что кеширование = просто добавить Redis.
Этого недостаточно.
Без правильной стратегии приложение всё равно будет тормозить на масштабе.
Вот простой чит-лист по кешированию
- Cache Aside (ленивая загрузка)
- Write Through (сквозная запись)
- Write Back (отложенная запись)
- Read Through (чтение через кеш)
- TTL и вытеснение
👉 @BackendPortal
Этого недостаточно.
Без правильной стратегии приложение всё равно будет тормозить на масштабе.
Вот простой чит-лист по кешированию
- Cache Aside (ленивая загрузка)
- Write Through (сквозная запись)
- Write Back (отложенная запись)
- Read Through (чтение через кеш)
- TTL и вытеснение
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
System Design Roadmap 2026 → от нуля до продакшен-уровня
Перестань смотреть рандомные видео.
Следуй этой последовательности:
Фаза 1: База
* Основы → Сетевое взаимодействие → Операционные системы
Фаза 2: Базовые компоненты
* Базы данных (SQL + NoSQL) → Кеширование (Redis) → Очереди сообщений (Kafka/RabbitMQ)
Фаза 3: Масштабирование и архитектура
* Балансировщики нагрузки → CDN → Шардирование → Репликация → Микросервисы (только когда есть необходимость)
Фаза 4: Продакшен
* Надёжность → Безопасность → Наблюдаемость (логи + метрики + трассировка)
* Ограничение запросов → Проектирование API (REST/gRPC/WebSocket) → Событийно-ориентированные системы
Фаза 5: Практика и мышление
* Функциональные и нефункциональные требования
* Оценка ёмкости → Высокоуровневый дизайн → Детальные разборы → Анализ компромиссов
* Обработка сбоев → Поиск узких мест → Постоянный редизайн
Практические проекты (по порядку):
Сервис коротких ссылок → Ограничитель запросов → Чат → Система уведомлений → Лента → Платёжная система → Райд-шеринг
Ежедневная практика:
Думать → Рисовать → Объяснять → Защищать компромиссы → Улучшать
Суть не в том, чтобы знать всё.
Важно — ясность + повторение + глубокая проработка
Сохрани этот роадмап.
Возвращайся к нему каждую неделю.
Не нужно 100 ресурсов.
Нужен правильный путь.
👉 @BackendPortal
Перестань смотреть рандомные видео.
Следуй этой последовательности:
Фаза 1: База
* Основы → Сетевое взаимодействие → Операционные системы
Фаза 2: Базовые компоненты
* Базы данных (SQL + NoSQL) → Кеширование (Redis) → Очереди сообщений (Kafka/RabbitMQ)
Фаза 3: Масштабирование и архитектура
* Балансировщики нагрузки → CDN → Шардирование → Репликация → Микросервисы (только когда есть необходимость)
Фаза 4: Продакшен
* Надёжность → Безопасность → Наблюдаемость (логи + метрики + трассировка)
* Ограничение запросов → Проектирование API (REST/gRPC/WebSocket) → Событийно-ориентированные системы
Фаза 5: Практика и мышление
* Функциональные и нефункциональные требования
* Оценка ёмкости → Высокоуровневый дизайн → Детальные разборы → Анализ компромиссов
* Обработка сбоев → Поиск узких мест → Постоянный редизайн
Практические проекты (по порядку):
Сервис коротких ссылок → Ограничитель запросов → Чат → Система уведомлений → Лента → Платёжная система → Райд-шеринг
Ежедневная практика:
Думать → Рисовать → Объяснять → Защищать компромиссы → Улучшать
Суть не в том, чтобы знать всё.
Важно — ясность + повторение + глубокая проработка
Сохрани этот роадмап.
Возвращайся к нему каждую неделю.
Не нужно 100 ресурсов.
Нужен правильный путь.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
Микросервисы — плохой выбор по умолчанию для 94% команд.
Зачем разбивать приложение на набор сервисов, которым нужно общаться через сеть.
На бумаге это выглядит как «правильный» подход. Масштабирование звучит привлекательно.
Но на практике я видел, как это ломается, шесть раз.
Команды из 5 инженеров поднимали 11 сервисов с несколькими очередями сообщений. Всё становилось медленнее.
Деплой, который занимал минуты, растягивался до 35 минут из-за зависимостей.
Отладка превращалась в кошмар: один баг — и приходится трейсить запрос через несколько сервисов и кодовых баз.
Сложность не уменьшилась. Она просто распределилась.
Микросервисы — это решение под масштабирование, но большинство команд внедряют их слишком рано, когда проблемы масштаба ещё нет.
Если ты всё ещё работаешь на localhost, основная проблема — не масштаб. Это стабильный релиз.
Когда микросервисы имеют смысл:
- команды блокируют работу друг друга
- части системы требуют независимого масштабирования
- есть нормальная трассировка в проде, и можно отлаживать без угадывания
Если этого нет — платишь налог распределённых систем без реальной выгоды.
Начинай с монолита и держи модульность. Делить стоит только тогда, когда связность начинает тормозить разработку.
Большинство обсуждений «нам нужны микросервисы» на деле не про архитектуру.
Они про грязную кодовую базу или болезненные деплои.
Сначала решаются эти проблемы.
Простые системы легче понимать. Перегруженные обычно разваливаются под собственным весом.
👉 @BackendPortal
Зачем разбивать приложение на набор сервисов, которым нужно общаться через сеть.
На бумаге это выглядит как «правильный» подход. Масштабирование звучит привлекательно.
Но на практике я видел, как это ломается, шесть раз.
Команды из 5 инженеров поднимали 11 сервисов с несколькими очередями сообщений. Всё становилось медленнее.
Деплой, который занимал минуты, растягивался до 35 минут из-за зависимостей.
Отладка превращалась в кошмар: один баг — и приходится трейсить запрос через несколько сервисов и кодовых баз.
Сложность не уменьшилась. Она просто распределилась.
Микросервисы — это решение под масштабирование, но большинство команд внедряют их слишком рано, когда проблемы масштаба ещё нет.
Если ты всё ещё работаешь на localhost, основная проблема — не масштаб. Это стабильный релиз.
Когда микросервисы имеют смысл:
- команды блокируют работу друг друга
- части системы требуют независимого масштабирования
- есть нормальная трассировка в проде, и можно отлаживать без угадывания
Если этого нет — платишь налог распределённых систем без реальной выгоды.
Начинай с монолита и держи модульность. Делить стоит только тогда, когда связность начинает тормозить разработку.
Большинство обсуждений «нам нужны микросервисы» на деле не про архитектуру.
Они про грязную кодовую базу или болезненные деплои.
Сначала решаются эти проблемы.
Простые системы легче понимать. Перегруженные обычно разваливаются под собственным весом.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14💊3
Почему
Хотя эту конструкцию используют почти в каждом Dockerfile (включая «рекомендованные», сгенерированные через
Я нашёл практическое задание, которое показывает проблему в действии: https://labs.iximiuz.com/challenges/graceful-termination-for-nodejs-container
Советую пройти, чтобы быстрее находить и избегать подобных багов в проде🫡
👉 @BackendPortal
["npm", "start"] — плохой выбор для CMD в Dockerfile Хотя эту конструкцию используют почти в каждом Dockerfile (включая «рекомендованные», сгенерированные через
create-react-app и подобные), ["npm", "start"] в CMD создаёт лишнюю оболочку в дереве процессов контейнера. Это мешает корректной обработке сигналов — и в итоге может сломать graceful shutdown вашего приложения.Я нашёл практическое задание, которое показывает проблему в действии: https://labs.iximiuz.com/challenges/graceful-termination-for-nodejs-container
Советую пройти, чтобы быстрее находить и избегать подобных багов в проде
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2
В России можно посещать IT-мероприятия хоть каждый день: как оффлайн, так и онлайн
Но где их находить? Как узнавать о них раньше, чем когда все начнут выкладывать фотографии оттуда?
Переходите на канал IT-Мероприятия России. В нём каждый день анонсируются мероприятия со всех городов России
📆 в канале размещаются как онлайн, так и оффлайн мероприятия;
👩💻 можно найти ивенты по любому стеку: программирование, frontend-backend разработка, кибербезопасность, дата-аналитика, osint, devops и другие;
🎙 разнообразные форматы мероприятий: митапы с коллегами по цеху, конференции и вебинары с известными опытными специалистами, форумы и олимпиады от важных представителей индустрии и многое другое
А чтобы не искать по разным форумам и чатам новости о предстоящих ивентах:
🚀 IT-мероприятия России — подписывайся и будь в курсе всех предстоящих мероприятий!
Но где их находить? Как узнавать о них раньше, чем когда все начнут выкладывать фотографии оттуда?
Переходите на канал IT-Мероприятия России. В нём каждый день анонсируются мероприятия со всех городов России
А чтобы не искать по разным форумам и чатам новости о предстоящих ивентах:
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍1🔥1
Многие backend-разработчики недооценивают структуру папок на раннем этапе.
Не потому что им всё равно, а потому что всё работает… пока не перестаёт.
Когда в приложении 5 файлов — подходит любая организация.
Когда становится 500 файлов, структура начинает определять:
→ как быстро ты дебажишь
→ насколько безопасно добавляешь фичи
→ поймут ли новый инженеры код
Это не вопрос стиля.
Это то, что не даёт системе развалиться под собственной сложностью.
Большинство новичков думают, что
структура папок = группировка файлов.
Это только половина картины.
Основная идея:
каждый слой должен иметь одну чёткую ответственность
Для Node.js приложения часто выглядит так:
routes → обработка HTTP
controllers → преобразование request/response
services → бизнес-логика
repositories → доступ к базе данных
models → структура данных
Простое правило:
если это смешивать, появляется путаница. если разделять — появляется ясность.
Добавление фичи — это не только написание кода.
Это ответы на вопросы:
→ где должна жить эта логика?
→ от чего она должна зависеть?
→ от чего она НЕ должна зависеть?
Если структура слабая:
→ логика размазывается по проекту
→ файлы разрастаются
→ изменения ломают несвязанные части
Если структура сильная:
→ понятно, куда писать код
→ изменения локализованы
→ дебаг быстрее
Плохой подход:
→ маршрут напрямую ходит в базу
→ бизнес-логика разбросана
Хороший подход:
route → middleware → controller → service → repository
Теперь при баге:
→ не нужно искать по всему проекту
→ есть понятный путь исполнения
Примечание: иногда код репозитория пишут прямо в сервисе. Это тоже нормально, зависит от подхода и команды.
Вопросы, которые стоит задавать к каждому файлу:
→ за что он отвечает
→ кто имеет право его вызывать
→ о чём он вообще не должен знать
Если на них есть чёткие ответы — структура, скорее всего, нормальная.
👉 @BackendPortal
Не потому что им всё равно, а потому что всё работает… пока не перестаёт.
Когда в приложении 5 файлов — подходит любая организация.
Когда становится 500 файлов, структура начинает определять:
→ как быстро ты дебажишь
→ насколько безопасно добавляешь фичи
→ поймут ли новый инженеры код
Это не вопрос стиля.
Это то, что не даёт системе развалиться под собственной сложностью.
Большинство новичков думают, что
структура папок = группировка файлов.
Это только половина картины.
Основная идея:
каждый слой должен иметь одну чёткую ответственность
Для Node.js приложения часто выглядит так:
routes → обработка HTTP
controllers → преобразование request/response
services → бизнес-логика
repositories → доступ к базе данных
models → структура данных
Простое правило:
если это смешивать, появляется путаница. если разделять — появляется ясность.
Добавление фичи — это не только написание кода.
Это ответы на вопросы:
→ где должна жить эта логика?
→ от чего она должна зависеть?
→ от чего она НЕ должна зависеть?
Если структура слабая:
→ логика размазывается по проекту
→ файлы разрастаются
→ изменения ломают несвязанные части
Если структура сильная:
→ понятно, куда писать код
→ изменения локализованы
→ дебаг быстрее
Плохой подход:
→ маршрут напрямую ходит в базу
→ бизнес-логика разбросана
Хороший подход:
route → middleware → controller → service → repository
Теперь при баге:
→ не нужно искать по всему проекту
→ есть понятный путь исполнения
Примечание: иногда код репозитория пишут прямо в сервисе. Это тоже нормально, зависит от подхода и команды.
Вопросы, которые стоит задавать к каждому файлу:
→ за что он отвечает
→ кто имеет право его вызывать
→ о чём он вообще не должен знать
Если на них есть чёткие ответы — структура, скорее всего, нормальная.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5💊1
Термины, которые действительно должен знать каждый разработчик
• Иммутабельность. Данные, которые нельзя изменить после создания — вместо этого при обновлении создаются новые копии.
• Чистые функции. Функции, которые при одинаковом входе всегда возвращают одинаковый результат и не имеют побочных эффектов.
• Побочные эффекты. Любое внешнее воздействие вне функции (например, логгирование, вызов API, изменение внешнего состояния).
• Референциальная прозрачность. Выражение можно заменить его значением без изменения поведения программы.
• Мутация состояния. Изменение значения переменной или объекта со временем — часто не приветствуется в функциональном программировании.
• Идемпотентность . Операция, которую можно выполнять многократно без изменения результата после первого применения.
• Декларативное программирование. Описание того, что нужно сделать, а не как это сделать (например, SQL, React, HTML).
• Императивное программирование. Пошаговые инструкции для выполнения задачи (например, циклы, условные операторы).
• Мемоизация. Кеширование результата функции, чтобы при повторных вызовах с теми же аргументами результат возвращался мгновенно.
• Когезия. Насколько чётко и логично связаны обязанности класса — высокая когезия = лучше дизайн.
• Тесная связанность. Классы чрезмерно зависят от внутренней реализации друг друга — изменения становятся рискованными.
• Утиная типизация. «Если выглядит как утка и крякает как утка — значит, это утка» — тип проверяется по поведению, а не по наследованию.
• Срезка объекта. При присваивании объекта производного класса объекту базового типа теряются дополнительные поля/методы — типичная ловушка в C++.
👉 @BackendPortal
• Иммутабельность. Данные, которые нельзя изменить после создания — вместо этого при обновлении создаются новые копии.
• Чистые функции. Функции, которые при одинаковом входе всегда возвращают одинаковый результат и не имеют побочных эффектов.
• Побочные эффекты. Любое внешнее воздействие вне функции (например, логгирование, вызов API, изменение внешнего состояния).
• Референциальная прозрачность. Выражение можно заменить его значением без изменения поведения программы.
• Мутация состояния. Изменение значения переменной или объекта со временем — часто не приветствуется в функциональном программировании.
• Идемпотентность . Операция, которую можно выполнять многократно без изменения результата после первого применения.
• Декларативное программирование. Описание того, что нужно сделать, а не как это сделать (например, SQL, React, HTML).
• Императивное программирование. Пошаговые инструкции для выполнения задачи (например, циклы, условные операторы).
• Мемоизация. Кеширование результата функции, чтобы при повторных вызовах с теми же аргументами результат возвращался мгновенно.
• Когезия. Насколько чётко и логично связаны обязанности класса — высокая когезия = лучше дизайн.
• Тесная связанность. Классы чрезмерно зависят от внутренней реализации друг друга — изменения становятся рискованными.
• Утиная типизация. «Если выглядит как утка и крякает как утка — значит, это утка» — тип проверяется по поведению, а не по наследованию.
• Срезка объекта. При присваивании объекта производного класса объекту базового типа теряются дополнительные поля/методы — типичная ловушка в C++.
Please open Telegram to view this post
VIEW IN TELEGRAM
💊3🔥1
Обсудим лучшие практики в разработке высоконагруженных систем и разберём реальные рабочие кейсы на примере сервисов с аудиторией в 100+ миллионов пользователей.
Когда: 16 мая, 12:00 мск
Где: офлайн в Москве и онлайн
В программе — два зала с докладами и решением практических задач.
«Направленный ациклический граф в PostgreSQL: как мы научили реляционную базу хранить оргструктуру на 500 тыс. пользователей»
//Спикер: Малик Минубаев, разработчик в B2B-платформе
«Как Яндекс Диск выдерживает сотни гигабит входящего трафика: устройство балансировки загрузок»
//Спикер: Илья Абрамов, разработчик в Диске
«Как формировать технологический стек и не погибнуть в священных войнах: от хаоса к процессам и техрадару»
//Спикер: Дмитрий Сафонов, руководитель команды разработки платформы микросервисов
«Зачем и как бэкендеру расти в карьере в 2026 году»
//Спикер: Дмитрий Соломонов, руководитель группы B2B-разработки бэкенда Диска
«Семь раз подумай, один раз пошардируй: как мы начали горизонтально масштабировать метаданные чатов Телемоста»
//Спикер: Никита Звонарев, разработчик в Мессенджере🚀 «Марс: великое противостояние»
//Спикер: Владимир Сурдин, астроном, кандидат физико-математических наук, доцент
Параллельно будут работать зоны открытого общения — можно в любой момент подключиться к обсуждениям с инженерами Яндекс 360 и провести время с пользой!
Please open Telegram to view this post
VIEW IN TELEGRAM
Перед тем как добавлять индекс в Постгрес (ускоряющий доступ к данным механизм), ответь на 4 вопроса.
Я вижу эту ошибку в ревью кода каждую неделю.
Появляется медленный запрос → добавляют индекс → считают, что проблема решена.
Но в половине случаев становится хуже.
Перед добавлением индекса проверь:
1. Используется ли колонка в ГДЕ, СОЕДИНЕНИЯХ или СОРТИРОВКЕ ПО
Если она встречается только в ВЫБРАТЬ, индекс почти не даст эффекта.
2. Какой размер таблицы
Постгрес выбирает между полным сканированием и индексом на основе стоимости.
Если возвращается большая часть строк, он может игнорировать индекс.
3. Какое соотношение чтений и записей
Индексы ускоряют чтение, но каждая вставка и обновление их обслуживает.
На таблицах с частыми записями каждый индекс добавляет нагрузку.
4. Какая кардинальность колонки
Индексы лучше работают, когда сильно сужают выборку.
Колонки с малым числом уникальных значений (низкая кардинальность, например перечисления или булевы поля) сами по себе плохо фильтруют, но могут помогать в комбинации.
Сначала запускай план выполнения запроса (объяснение плана выполнения).
Потом запускай снова после изменений.
Если стоимость не падает — индекс не помогает.
Удаляй его.
Индексы не бесплатные.
Это всегда компромисс.
Большинство добавляет индексы чтобы “починить” запросы.
Более сильный подход — чинить сами запросы, чтобы индексы не требовались.
👉 @BackendPortal
Я вижу эту ошибку в ревью кода каждую неделю.
Появляется медленный запрос → добавляют индекс → считают, что проблема решена.
Но в половине случаев становится хуже.
Перед добавлением индекса проверь:
1. Используется ли колонка в ГДЕ, СОЕДИНЕНИЯХ или СОРТИРОВКЕ ПО
Если она встречается только в ВЫБРАТЬ, индекс почти не даст эффекта.
2. Какой размер таблицы
Постгрес выбирает между полным сканированием и индексом на основе стоимости.
Если возвращается большая часть строк, он может игнорировать индекс.
3. Какое соотношение чтений и записей
Индексы ускоряют чтение, но каждая вставка и обновление их обслуживает.
На таблицах с частыми записями каждый индекс добавляет нагрузку.
4. Какая кардинальность колонки
Индексы лучше работают, когда сильно сужают выборку.
Колонки с малым числом уникальных значений (низкая кардинальность, например перечисления или булевы поля) сами по себе плохо фильтруют, но могут помогать в комбинации.
Сначала запускай план выполнения запроса (объяснение плана выполнения).
Потом запускай снова после изменений.
Если стоимость не падает — индекс не помогает.
Удаляй его.
Индексы не бесплатные.
Это всегда компромисс.
Большинство добавляет индексы чтобы “починить” запросы.
Более сильный подход — чинить сами запросы, чтобы индексы не требовались.
Please open Telegram to view this post
VIEW IN TELEGRAM