Превращай сложные диаграммы по system design в интерактивные визуализации 🔥
Есть опенсорс-проект, который берет обычную диаграмму архитектуры и превращает ее в интерактивный вид, где можно ходить по компонентам и разбирать схему по слоям.
👉 @BackendPortal
Есть опенсорс-проект, который берет обычную диаграмму архитектуры и превращает ее в интерактивный вид, где можно ходить по компонентам и разбирать схему по слоям.
Please open Telegram to view this post
VIEW IN TELEGRAM
Не пропускай эти 6 задач по многопоточности перед собесом:
1. Producer-Consumer
Решай через BlockingQueue или wait/notify.
2. Печать 1-100 (2 потока)
Чередование через общий счетчик + lock/монитор.
3. Печать “ABCABC...”
Синхронизируй 3 потока через Lock или notifyAll.
4. Свой Thread Pool
Собери пул: воркеры + очередь задач.
5. Сценарий дедлока
Сымитируй и покажи, как избежать через порядок захвата локов.
6. Rate Limiter
Реализуй Token Bucket или Leaky Bucket.
👉 @BackendPortal
1. Producer-Consumer
Решай через BlockingQueue или wait/notify.
2. Печать 1-100 (2 потока)
Чередование через общий счетчик + lock/монитор.
3. Печать “ABCABC...”
Синхронизируй 3 потока через Lock или notifyAll.
4. Свой Thread Pool
Собери пул: воркеры + очередь задач.
5. Сценарий дедлока
Сымитируй и покажи, как избежать через порядок захвата локов.
6. Rate Limiter
Реализуй Token Bucket или Leaky Bucket.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7
Давайте про вещь вроде бы очевидную, но с цифрами.
Теоретически и массивы, и связные списки проходят за O(n). Но если прогнать простой бенчмарк на суммирование 100k целых, получается так:
- массив: 68 312 нс
- связный список: 181 567 нс
Массив примерно в 3 раза быстрее. Алгоритм тот же, асимптотика та же, а разница в производительности огромная.
Причина в работе с кэшем. Когда мы читаем array[0], процессор подтягивает всю кэш-линию (64 байта). Это сразу захватывает элементы с array[0] по array[15]. Следующие ~15 обращений почти бесплатные. Попадания в кэш у массивов около 94%.
Со списками всё хуже: указатели, разрозненные аллокации через malloc(), ноды раскиданы по памяти. Каждое следующее значение может быть в другой кэш-линии, отсюда частые промахи и около 70% cache miss.
Это хороший пример, почему Big O — только часть картины. Пространственная локальность и дружелюбность к кэшу дают 2–3x разницу даже при одинаковой теоретической сложности.
Наверняка вы и так это знали, но такие цифры наглядно показывают, насколько выигрывают алгоритмы, дружные с кэшем.
👉 @BackendPortal
Теоретически и массивы, и связные списки проходят за O(n). Но если прогнать простой бенчмарк на суммирование 100k целых, получается так:
- массив: 68 312 нс
- связный список: 181 567 нс
Массив примерно в 3 раза быстрее. Алгоритм тот же, асимптотика та же, а разница в производительности огромная.
Причина в работе с кэшем. Когда мы читаем array[0], процессор подтягивает всю кэш-линию (64 байта). Это сразу захватывает элементы с array[0] по array[15]. Следующие ~15 обращений почти бесплатные. Попадания в кэш у массивов около 94%.
Со списками всё хуже: указатели, разрозненные аллокации через malloc(), ноды раскиданы по памяти. Каждое следующее значение может быть в другой кэш-линии, отсюда частые промахи и около 70% cache miss.
Это хороший пример, почему Big O — только часть картины. Пространственная локальность и дружелюбность к кэшу дают 2–3x разницу даже при одинаковой теоретической сложности.
Наверняка вы и так это знали, но такие цифры наглядно показывают, насколько выигрывают алгоритмы, дружные с кэшем.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🤔1
Бесплатный API с моделями ИИ — без привязки карты.
✓ 1000 запросов в день к моделям OpenAI
✓ Есть Qwen 3, Kimi K2 и Llama
✓ Аудио, голос, reasoning и прочее
Сервис называется Groq → http://groq.com
👉 @BackendPortal
✓ 1000 запросов в день к моделям OpenAI
✓ Есть Qwen 3, Kimi K2 и Llama
✓ Аудио, голос, reasoning и прочее
Сервис называется Groq → http://groq.com
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯4
ORM на больших нагрузках — это скорее антипаттерн.
Когда вы выходите на масштаб, большинство команд от них уходит, потому что абстракция между БД и языком так и не держится до конца.
На проде с нагрузкой ORM почти всегда мешает использовать нативные оптимизации базы. А если вы уже пишете сырой SQL, чтобы обойти ограничения ORM, то проще сразу работать через prepared statements.
Да, ORM скрывает сложность запросов, но именно из-за этого легко отправить в прод неэффективные N+1 запросы и даже не заметить. А потом дебажить это в продакшн-инцидент — тот ещё гемор
ORM отстают от возможностей СУБД. Индексы, query hints, новые фичи — либо использовать неудобно (вспомните prefetch в Django ORM), либо поддержки просто нет. В итоге вы ограничены самым примитивным функционалом, который ORM вообще умеет, вместо того чтобы нормально раскрывать потенциал базы.
На масштабе явные SQL-запросы проще, быстрее и легче оптимизировать. Когнитивные расходы на маппинг объектов в таблицы себя уже не оправдывают.
Справедливости ради — ORM хороши для прототипов и быстрого выхода на рынок. В начале можно, но важно заранее иметь план, как потом от этого уйти.
Говорю из опыта: звучит легко, а на деле — ух, не всегда так просто.
👉 @BackendPortal
Когда вы выходите на масштаб, большинство команд от них уходит, потому что абстракция между БД и языком так и не держится до конца.
На проде с нагрузкой ORM почти всегда мешает использовать нативные оптимизации базы. А если вы уже пишете сырой SQL, чтобы обойти ограничения ORM, то проще сразу работать через prepared statements.
Да, ORM скрывает сложность запросов, но именно из-за этого легко отправить в прод неэффективные N+1 запросы и даже не заметить. А потом дебажить это в продакшн-инцидент — тот ещё гемор
ORM отстают от возможностей СУБД. Индексы, query hints, новые фичи — либо использовать неудобно (вспомните prefetch в Django ORM), либо поддержки просто нет. В итоге вы ограничены самым примитивным функционалом, который ORM вообще умеет, вместо того чтобы нормально раскрывать потенциал базы.
На масштабе явные SQL-запросы проще, быстрее и легче оптимизировать. Когнитивные расходы на маппинг объектов в таблицы себя уже не оправдывают.
Справедливости ради — ORM хороши для прототипов и быстрого выхода на рынок. В начале можно, но важно заранее иметь план, как потом от этого уйти.
Говорю из опыта: звучит легко, а на деле — ух, не всегда так просто.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🤔5
Нашёл репозиторий, который реально помогает выбрать HTTP-фреймворк под Go. Там интерактивный гайд с 25 типовыми задачами — от роутинга до вебсокетов — причём каждый пример написан на разных движках: net/http, Chi, Gin, Echo, Fiber и Mizu.
Изучаем
👉 @BackendPortal
Изучаем
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - go-mizu/go-fw: A practical, code-driven guide to learning HTTP frameworks in Go.
A practical, code-driven guide to learning HTTP frameworks in Go. - go-mizu/go-fw
👍2🔥1
Когда стоит отказаться от классического ACID и 2PC и перейти к паттерну SAGA?
Речь про микросервисы, где одна бизнес-операция (например, оформление заказа) проходит через кучу сервисов:
Order → Payment → Inventory → Notification.
→ нет общей базы
→ нет распределённой транзакции
→ посреди процесса что-то падает: платеж прошёл, инвентарь не смог, нотификации отстрелялись частично
В чём реальная проблема:
Мы пытаемся добиться транзакционной согласованности между сервисами без глобальной транзакции.
Локальные ACID-транзакции уже не спасают, как только мы пересекаем границы сервисов.
Это и есть distributed transaction проблема.
Решение: паттерн SAGA
Разбиваем длинную бизнес-транзакцию на цепочку локальных шагов, у каждого есть компенсирующее действие.
Как это работает:
• каждый сервис делает свою локальную транзакцию
• если шаг заваливается, предыдущие компенсируются (а не откатываются магически)
• консистентность достигается не сразу, а со временем (eventual consistency)
Есть два распространённых подхода:
1. Choreography — сервисы реагируют на события, без центра
2. Orchestration — координатор управляет всем сценарием
Важно:
• состояние SAGA хранится персистентно, не в памяти
• нужны ретраи, таймауты и идемпотентность
• без нормальной наблюдаемости/логирования будет боль
Итог: SAGA — это про управление ошибками между сервисами, когда глобальных транзакций нет, а согласованность всё ещё нужна.
👉 @BackendPortal
Речь про микросервисы, где одна бизнес-операция (например, оформление заказа) проходит через кучу сервисов:
Order → Payment → Inventory → Notification.
→ нет общей базы
→ нет распределённой транзакции
→ посреди процесса что-то падает: платеж прошёл, инвентарь не смог, нотификации отстрелялись частично
В чём реальная проблема:
Мы пытаемся добиться транзакционной согласованности между сервисами без глобальной транзакции.
Локальные ACID-транзакции уже не спасают, как только мы пересекаем границы сервисов.
Это и есть distributed transaction проблема.
Решение: паттерн SAGA
Разбиваем длинную бизнес-транзакцию на цепочку локальных шагов, у каждого есть компенсирующее действие.
Как это работает:
• каждый сервис делает свою локальную транзакцию
• если шаг заваливается, предыдущие компенсируются (а не откатываются магически)
• консистентность достигается не сразу, а со временем (eventual consistency)
Есть два распространённых подхода:
1. Choreography — сервисы реагируют на события, без центра
2. Orchestration — координатор управляет всем сценарием
Важно:
• состояние SAGA хранится персистентно, не в памяти
• нужны ретраи, таймауты и идемпотентность
• без нормальной наблюдаемости/логирования будет боль
Итог: SAGA — это про управление ошибками между сервисами, когда глобальных транзакций нет, а согласованность всё ещё нужна.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5🔥3
Открытый, лёгкий аналог Supabase/Firebase с аутентификацией, UI для базы данных и хранением медиа, заточенный под работу в Next.js, React Router, Astro, Cloudflare, Node и других средах.
https://alternativeto.net/software/bknd-io/about/
👉 @BackendPortal
https://alternativeto.net/software/bknd-io/about/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2❤1
Proxyman_App 6.3 для macOS добавляет поддержку HTTP/2, захват трафика на localhost для Chrome и Firefox, prettify для XML, новые команды в CLI, поддержку командных лицензий, определение IPv4-адресов, улучшенную проверку сертификатов и другие изменения.
👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4
Совет по Kubernetes
С этим ресурсом можно утащить управление схемой БД прямо в Kubernetes
» Описываешь схему как K8s-ресурсы
» Atlas сам сверяет текущее состояние БД и генерирует ALTER’ы
» Хранишь ресурс в Git и синкаешь через Argo CD, чтобы конфигурация приложения и схема БД управлялись одинаково
👉 @BackendPortal
С этим ресурсом можно утащить управление схемой БД прямо в Kubernetes
» Описываешь схему как K8s-ресурсы
» Atlas сам сверяет текущее состояние БД и генерирует ALTER’ы
» Хранишь ресурс в Git и синкаешь через Argo CD, чтобы конфигурация приложения и схема БД управлялись одинаково
apiVersion: db.atlasgo.io/v1alpha1
kind: AtlasSchema
metadata:
name: sample-schema
spec:
urlFrom:
secretKeyRef:
key: url
name: postgresql-credentials
schema:
sql: |
create table person (
id serial primary key,
name varchar(255),
gender varchar(255),
age int,
external_id int // (+)
);
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍2💊2
Kafka и NATS — это не просто два брокера, разница глубже: pull против push моделей.
В Kafka консьюмеры сами тянут сообщения по оффсету и сами решают, когда читать.
Это удобно для backpressure, батчевых задач и пайплайнов с частыми переигрываниями данных.
В NATS всё наоборот: push-консьюмеры получают данные сразу по факту появления. Быстро, реактивно, без ощутимой задержки.
JetStream позволяет смешивать подходы: push для широкого фан-аута, pull для контролируемых воркеров. Комбо, которое закрывает оба сценария.
Но есть нюанс: push + медленный обработчик = тихий рост нагрузки в памяти. Держите под контролем
Pull-режим в NATS отлично заходит для автоскейлинга воркеров: вытянули N сообщений → масштабируем поды дальше.
Kafka: настройка
Общее правило: нужно стримить и переобрабатывать — берут Kafka. Нужны мгновенные реакции и низкая задержка — ближе NATS.
👉 @BackendPortal
В Kafka консьюмеры сами тянут сообщения по оффсету и сами решают, когда читать.
Это удобно для backpressure, батчевых задач и пайплайнов с частыми переигрываниями данных.
В NATS всё наоборот: push-консьюмеры получают данные сразу по факту появления. Быстро, реактивно, без ощутимой задержки.
JetStream позволяет смешивать подходы: push для широкого фан-аута, pull для контролируемых воркеров. Комбо, которое закрывает оба сценария.
Но есть нюанс: push + медленный обработчик = тихий рост нагрузки в памяти. Держите под контролем
max_ack_pending.Pull-режим в NATS отлично заходит для автоскейлинга воркеров: вытянули N сообщений → масштабируем поды дальше.
Kafka: настройка
max.poll.interval.ms важнее, чем кажется. Промахнулись — поймаете ребаланс и просадку по работе консьюмера.Общее правило: нужно стримить и переобрабатывать — берут Kafka. Нужны мгновенные реакции и низкая задержка — ближе NATS.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
Твое приложение тормозит не потому что оно плохое. Оно тормозит потому что растет.
В начале все идет легко.
Мало юзеров.
Ответы летят.
Никакого давления.
Берешь Supabase и все просто работает.
Авторизация выглядит аккуратно.
Данные ощущаются надежными.
Время уходит на разработку, а не на фикс проблем
Потом нагрузка начинает расти.
Запросы копятся.
Одни и те же данные дергаются снова и снова.
Бэкенд тихо начинает пахать сильнее, чем должен.
Ничего не падает, но ощущение уже не то.
Вот тут в игру заходит Redis.
Не как огромная архитектурная перестройка.
Не потому что все сломалось.
А потому что рост меняет поведение системы.
Supabase держит достоверность и консистентность.
Redis берет на себя скорость, повторяющиеся запросы и нагрузку.
Один дает структуру.
Второй дает пространство для дыхания.
Страницы грузятся быстрее.
Пики трафика перестают пугать.
Не надо проверять логи каждые пару минут.
Пользователь не замечает технологию, он просто чувствует что все работает плавно.
И вот это настоящая победа.
Масштабирование это не про "делать больше". Это про убрать трение.
Supabase дает стабильность. Redis дает свободу.
Вместе они позволяют работать спокойно,
выкатывать фичи увереннои расти без всяких нежданчиков
👉 @BackendPortal
В начале все идет легко.
Мало юзеров.
Ответы летят.
Никакого давления.
Берешь Supabase и все просто работает.
Авторизация выглядит аккуратно.
Данные ощущаются надежными.
Время уходит на разработку, а не на фикс проблем
Потом нагрузка начинает расти.
Запросы копятся.
Одни и те же данные дергаются снова и снова.
Бэкенд тихо начинает пахать сильнее, чем должен.
Ничего не падает, но ощущение уже не то.
Вот тут в игру заходит Redis.
Не как огромная архитектурная перестройка.
Не потому что все сломалось.
А потому что рост меняет поведение системы.
Supabase держит достоверность и консистентность.
Redis берет на себя скорость, повторяющиеся запросы и нагрузку.
Один дает структуру.
Второй дает пространство для дыхания.
Страницы грузятся быстрее.
Пики трафика перестают пугать.
Не надо проверять логи каждые пару минут.
Пользователь не замечает технологию, он просто чувствует что все работает плавно.
И вот это настоящая победа.
Масштабирование это не про "делать больше". Это про убрать трение.
Supabase дает стабильность. Redis дает свободу.
Вместе они позволяют работать спокойно,
выкатывать фичи увереннои расти без всяких нежданчиков
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6💊3👍2
Complete Backend Development Roadmap (all Major Tech Stacks).pdf
24.9 KB
Полный роудмап по Backend-разработке (все основные стеки)
Это подробный, реально производственный роудмап по бэкенду, который закрывает все ключевые технологии, используемые в боевых системах.|
👉 @BackendPortal
Это подробный, реально производственный роудмап по бэкенду, который закрывает все ключевые технологии, используемые в боевых системах.|
Please open Telegram to view this post
VIEW IN TELEGRAM
10 задач по Docker, которые стоит закрыть перед переходом на Kubernetes
1. Задокеризировать продакшн-веб-приложение с использованием переменных окружения.
2. Собрать оптимизированные multi-stage Dockerfile’ы.
3. Запускать контейнеры не от root ради безопасности.
4. Пушить версионированные образы в Docker Hub или ECR.
5. Поднимать мультисервисные стеки через docker-compose.
6. Управлять персистентными данными с помощью Docker volumes.
7. Добавить healthcheck’и в контейнеры.
8. Сканировать образы на уязвимости и фиксить их.
9. Автоматизировать сборку и публикацию образов в CI.
10. Дебажить контейнеры через логи и docker exec.
👉 @BackendPortal
1. Задокеризировать продакшн-веб-приложение с использованием переменных окружения.
2. Собрать оптимизированные multi-stage Dockerfile’ы.
3. Запускать контейнеры не от root ради безопасности.
4. Пушить версионированные образы в Docker Hub или ECR.
5. Поднимать мультисервисные стеки через docker-compose.
6. Управлять персистентными данными с помощью Docker volumes.
7. Добавить healthcheck’и в контейнеры.
8. Сканировать образы на уязвимости и фиксить их.
9. Автоматизировать сборку и публикацию образов в CI.
10. Дебажить контейнеры через логи и docker exec.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🔥1
Этот GitHub-репозиторий выглядит просто дико
Это огромная подборка из 2600+ API для скрейпинга, с помощью которых можно вытаскивать данные с сайтов, соцсетей, e-commerce-платформ и много чего ещё.
👉 @BackendPortal
Это огромная подборка из 2600+ API для скрейпинга, с помощью которых можно вытаскивать данные с сайтов, соцсетей, e-commerce-платформ и много чего ещё.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7
This media is not supported in your browser
VIEW IN TELEGRAM
Бесплатный API для определения геолокации по IP-адресу.
Безлимитные запросы и без регистрации.
→
Подходит для JavaScript, Python, PHP и любого другого языка.
👉 @BackendPortal
Безлимитные запросы и без регистрации.
→
ip․guideПодходит для JavaScript, Python, PHP и любого другого языка.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10
Правила выбора структур данных:
* Небольшие коллекции (<100) → линейный проход быстрее HashMap
(хэш + лишняя индирекция дороже, чем O(n))
* В основном чтение, записи редкие → иммутабельные структуры
(JIT оптимизирует, нет рехэша, проще рассуждать о коде)
* Высокая частота записей → избегай отсортированных структур
(ротации деревьев добавляют скрытую стоимость)
* Порядок нужен только на выходе → храни без порядка, сортируй при чтении
(одна сортировка дешевле, чем поддерживать порядок всегда)
* Частые итерации → оптимизируй локальность памяти
(arrays > ArrayList > HashMap > TreeMap)
* Hot path → избегай полиморфных структур
(виртуальные вызовы мешают инлайнингу)
* Стабильные ключи → заранее агрессивно задавай размер HashMap
(resize = всплеск латентности)
* Разреженные числовые ключи → массивы лучше мап
(смещение по индексу быстрее хэширования)
* Плотные enum-ключи → EnumMap
(реализация на массиве, без хэширования)
* Нужны и membership, и порядок → LinkedHashSet
(платишь памятью, но избегаешь TreeSet)
👉 @BackendPortal
* Небольшие коллекции (<100) → линейный проход быстрее HashMap
(хэш + лишняя индирекция дороже, чем O(n))
* В основном чтение, записи редкие → иммутабельные структуры
(JIT оптимизирует, нет рехэша, проще рассуждать о коде)
* Высокая частота записей → избегай отсортированных структур
(ротации деревьев добавляют скрытую стоимость)
* Порядок нужен только на выходе → храни без порядка, сортируй при чтении
(одна сортировка дешевле, чем поддерживать порядок всегда)
* Частые итерации → оптимизируй локальность памяти
(arrays > ArrayList > HashMap > TreeMap)
* Hot path → избегай полиморфных структур
(виртуальные вызовы мешают инлайнингу)
* Стабильные ключи → заранее агрессивно задавай размер HashMap
(resize = всплеск латентности)
* Разреженные числовые ключи → массивы лучше мап
(смещение по индексу быстрее хэширования)
* Плотные enum-ключи → EnumMap
(реализация на массиве, без хэширования)
* Нужны и membership, и порядок → LinkedHashSet
(платишь памятью, но избегаешь TreeSet)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
SQL-совет: как работает ORDER BY с несколькими колонками
Когда в запросе используется ORDER BY с несколькими полями, база сначала сортирует весь результат по первой колонке (в примере — sales).
Так формируются группы строк с одинаковым значением первичного поля, например все строки с sales = 12000.
Дальше включается вторичная сортировка (age ASC).
Она применяется не ко всей таблице, а только внутри этих групп.
В результате видно, что строки с одинаковым sales стоят рядом.
Например, Mira и Bob сгруппированы вместе, потому что у них одинаковые продажи (12000).
Первичная сортировка по sales DESC дала равенство, и тут в дело вступает второе поле.
Так как сортируем по age по возрастанию, Mira (30) идет перед Bob.
То же самое происходит для всех значений, которые совпали в первой сортировке:
каждое следующее поле в ORDER BY работает как тай-брейкер для предыдущего.
👉 @BackendPortal
Когда в запросе используется ORDER BY с несколькими полями, база сначала сортирует весь результат по первой колонке (в примере — sales).
Так формируются группы строк с одинаковым значением первичного поля, например все строки с sales = 12000.
Дальше включается вторичная сортировка (age ASC).
Она применяется не ко всей таблице, а только внутри этих групп.
В результате видно, что строки с одинаковым sales стоят рядом.
Например, Mira и Bob сгруппированы вместе, потому что у них одинаковые продажи (12000).
Первичная сортировка по sales DESC дала равенство, и тут в дело вступает второе поле.
Так как сортируем по age по возрастанию, Mira (30) идет перед Bob.
То же самое происходит для всех значений, которые совпали в первой сортировке:
каждое следующее поле в ORDER BY работает как тай-брейкер для предыдущего.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2