Backend Systems | balun.courses
رفتن به کانال در Telegram
Канал школы balun.courses про бэкенд-инженерию в продакшене: Kafka, PgSQL, Redis, Elasticsearch, observability и распределенные системы: https://clck.ru/3C8e7o
نمایش بیشترکشور مشخص نشده استدسته بندی مشخص نشده است
444
مشترکین
+124 ساعت
+27 روز
+230 روز
در حال بارگذاری دادهها
کانالهای مشابه
هیچ دادهای
مشکلی وجود دارد؟ لطفاً صفحه را تازه کنید یا با مدیر پشتیبانی ما تماس بگیرید.
ابر برچسبها
هیچ دادهای
مشکلی وجود دارد؟ لطفاً صفحه را تازه کنید یا با مدیر پشتیبانی ما تماس بگیرید.
اشارات ورودی و خروجی
---
---
---
---
---
---
جذب مشترکین
اکتبر '26اکتبر '26
اکتبر '26
+444
در 1 کانالها
| تاریخ | رشد مشترکین | اشارات | کانالها | |
| 19 اکتبر | +1 | |||
| 18 اکتبر | +1 | |||
| 17 اکتبر | 0 | |||
| 16 اکتبر | 0 | |||
| 15 اکتبر | 0 |
پستهای کانال
Сначала смеёмся, потом открываем pg_stat_user_tables 😔
Завтра, 13 октября, стартует курс по PostgreSQL. На практике разберём в том числе, почему таблица после массового DELETE всё ещё занимает те же 100 ГБ – и что вообще с этим делать в проде.
➡️ЗАПИСАТЬСЯ НА КУРС
| 2 | ⁉️Что вы реально сделаете за 1,5 месяца на курсе PostgreSQL
Можно перечислить 9 занятий, темы и технологии.
Но по такой программе сложно понять, что вы в итоге действительно будете уметь делать руками)
Поэтому собрали всё проще – через практику.
На курсе придётся специально создавать проблемы на учебном стенде: раздувать таблицы, разбирать плохие запросы, ловить проблемы конкурентного доступа, смотреть на lag реплики и диагностировать состояние базы.
А потом – разбираться, почему это произошло и какое решение здесь вообще имеет смысл.
В карточках показали, какие задачи вы пройдёте за курс и с чем закончите обучение ❤️
🗓Старт – 13 октября.
Курс рассчитан на Middle/Senior backend-разработчиков и архитекторов. За 1,5 месяца пройдём PostgreSQL с позиции разработчика – от внутреннего устройства и запросов до надёжности, troubleshooting и System Design.
➡️Подробнее о программе и запись на курс | 196 |
| 3 | ⚡️ Открыли предзапись на курс «Проектирование и разработка поисковых систем на базе Elasticsearch»
Пользователь может ошибиться в названии товара, описать документ своими словами или искать ответ в большой базе знаний. Поисковой системе нужно найти подходящие данные, расположить их в полезном порядке и быстро вернуть результат – даже когда документов миллионы.
На новом курсе разберем, как проектировать такой поиск: от сбора и индексации данных до релевантной выдачи, масштабирования и retrieval для AI-систем.
В программе:
• Полнотекстовый поиск: inverted index, BM25, ранжирование, обработка опечаток и синонимов.
• Поисковая инфраструктура: сбор и очистка данных, индексация, Search API, пагинация и кэширование.
• Семантический поиск: embeddings и поиск по смыслу, когда пользователь не знает точного названия.
• Поиск для AI: объединение полнотекстового и векторного поиска, reranking, retrieval для RAG и инструменты AI-агентов.
На практике за месяц соберете распределенный поисковый движок по Википедии: напишете crawler, подготовите документы для индексации, реализуете Search API и добавите семантический поиск.
🧍Преподаватель – Степан Ляхов, Senior Backend Engineer в TradingView. Ранее оптимизировал поисковую инфраструктуру в ViTech и проектировал ML-платформу персонализации и рекламного ранжирования в Magnit OMNI. Он же будет проверять домашние задания и отвечать на вопросы.
❗️Курс рассчитан на backend-разработчиков и инженеров уровня Middle+ и выше. Для старта нужны знание любого backend-языка, баз данных и основы System Design.
Сейчас можно заполнить анкету предзаписи: первыми сообщим о начале набора и предложим индивидуальные условия участия. Предзапись не обязывает к покупке.
✔️Программа и анкета предзаписи | 219 |
| 4 | PostgreSQL тоже иногда проходит путь Джейкоба из первой части «Сумерек» в последующие.
Главное – не пытаться прокачать его первым решением, которое пришло в голову :)
Собрали несколько вариантов «можно так / но лучше так» для ситуаций, которые регулярно встречаются в проде.
*Ненавязчиво напоминаем, что 13 октября стартует наш курс по PostgreSQL. Стоимость обучения увеличится через 8 часов* | 3 464 |
| 5 | Правильный ответ – Б. Длинная транзакция держит lock, остальные запросы ждут
Здесь одна транзакция захватила блокировку и слишком долго её не отпускала. Всё, что пыталось обратиться к тому же ресурсу, начало ждать.
Поэтому картина получается немного странная: CPU всего 35%, сами запросы обычно быстрые, но latency всё равно растёт. Просто значительную часть времени они вообще ничего не считают – стоят в очереди на lock ☹️
А пока запрос ждёт, соединение остаётся занятым. Таких запросов становится больше, connection pool постепенно заполняется, и через какое-то время уже начинает казаться, что проблема именно в нехватке соединений.
Хотя connections здесь закончились уже по дороге.
В pg_stat_activity я бы посмотрел на wait_event_type, wait_event, время начала транзакции и сам запрос. Быстро найти блокирующую сессию можно через pg_blocking_pids(pid):
SELECT
pid,
state,
wait_event_type,
wait_event,
xact_start,
pg_blocking_pids(pid),
query
FROM pg_stat_activity
WHERE wait_event_type IS NOT NULL;
Если несколько сессий ждут Lock, а pg_blocking_pids указывает у них на один и тот же PID, дальше уже понятно, куда копать: находим эту транзакцию и смотрим, почему она живёт так долго.
Кстати, с deadlock это путать не стоит. Deadlock PostgreSQL умеет обнаруживать и одну из конфликтующих транзакций в итоге прервёт. Обычная длинная блокировка может спокойно висеть гораздо дольше и за это время набрать за собой приличную очередь.
✔️На курсе по PostgreSQL такие инциденты тоже будем разбирать руками: искать блокирующие транзакции через pg_stat_activity, смотреть, кто кого ждёт, и восстанавливать цепочку до первопричины. | 287 |
| 6 | Куда полезете первым? | 230 |
| 7 | Прод падает, CPU 35%, памяти хватает. Что сломалось?
14:20. У API начинает расти latency: p95 уезжает примерно с 200 мс до 4-5 секунд. Через несколько минут часть запросов уже падает по timeout.
Смотрим на базу:
• CPU – 35%;
• памяти с запасом;
• по I/O ничего подозрительного;
• connection pool постепенно забивается.
Открываем pg_stat_activity – там много сессий в ожидании. | 252 |
| 8 | بدون متن... | 274 |
| 9 | Вы удалили половину строк из таблицы. Почему место на диске почти не освободилось?
Допустим, таблица весит 100 ГБ Удаляем половину строк. Смотрим размер – всё ещё почти 100 ГБ. Запускаем VACUUM. Размер почти не меняется.
Тут обычно возникает логичный вопрос: если данные удалены, почему место никуда не делось?
⚡Потому что DELETE в PostgreSQL не означает «вырезать строку из файла». Из-за MVCC старая версия строки ещё какое-то время остаётся внутри таблицы. Для новых транзакций она уже невидима, но физически место продолжает занимать.
Такие версии и становятся dead tuples.
С UPDATE похожая история. PostgreSQL обычно создаёт новую версию строки, а старая остаётся до тех пор, пока её можно безопасно убрать. Поэтому таблица с частыми обновлениями может заметно разрастаться, даже если количество актуальных строк почти не меняется.
Дальше подключается VACUUM.
Когда старая версия уже не нужна ни одной активной транзакции, VACUUM освобождает занятое ей место для повторного использования.
❗️Но тут есть момент, на котором часто спотыкаются: обычный VACUUM в первую очередь освобождает место внутри самой таблицы. Он не обязан вернуть эти гигабайты операционной системе.
То есть после удаления половины строк файл вполне может остаться примерно тех же 100 ГБ. Просто часть этого объёма PostgreSQL сможет потом использовать под новые INSERT и UPDATE.
Если мёртвых версий накапливается слишком много, начинается bloat.
Получается ситуация, когда актуальных данных, например, на 55 ГБ, а сама таблица весит 100. PostgreSQL всё ещё работает с большим объёмом страниц, чем реально нужно. Со временем это начинает бить и по чтению, и по размеру индексов.
Если нужно именно физически уменьшить файл на диске, это уже отдельная операция. Например, VACUUM FULL переписывает таблицу целиком и возвращает место ОС, но ценой блокировки. Поэтому запускать его в проде просто потому, что «таблица раздулась», – так себе идея.
После массового DELETE я бы смотрел не только на количество оставшихся строк. Нужны хотя бы dead tuples, состояние autovacuum и реальный размер relation. Если vacuum не успевает – дальше уже разбираться, почему.
На курсе по PostgreSQL это будем проверять руками: специально раздуем базу массовыми UPDATE и DELETE, посмотрим метрики до и после и разберём, как MVCC, dead tuples и vacuum ведут себя на практике.
🗓Старт курса – 13 октября. За 1,5 месяца разберём PostgreSQL с позиции разработчика: от MVCC, запросов и индексов до транзакций, масштабирования и troubleshooting. Основной упор — на практику и реальные production-сценарии. | 232 |
| 10 | Что происходит за одну учебную неделю на курсе Observability
Основное занятие проходит раз в неделю и занимает 1,5–2 часа. Но обучение не заканчивается после Zoom: часть времени уходит на самостоятельную практику и работу с материалом. В среднем на курс стоит ориентироваться примерно на 8 часов в неделю.
При этом искать восемь свободных часов подряд не нужно. Нагрузку можно распределить по неделе так, чтобы она вписывалась в рабочий график. На домашние задания стоит закладывать около 3 часов, а к материалам и записи занятия можно возвращаться тогда, когда удобно.
Например, неделя может выглядеть так:
〰️понедельник вечером - основное занятие, 1,5–2 часа
〰️середина недели - час-полтора на материалы или начало практики
〰️выходные - несколько часов на домашнее задание
〰️по ходу недели - вопросы в чат или на Q&A
Так обучение не приходится вмещать в один длинный вечер после работы. Если в одну неделю спокойно, а в другую совпали релиз или дедлайн, нагрузку можно перераспределить: занятия остаются в записи, поэтому к сложной теме можно вернуться позже, а практику не обязательно завершать сразу после урока.
В предыдущем посте мы показывали задание по поиску причины деградации. Подобная практика как раз предполагает отдельное время: сначала разобраться в подходе на занятии, затем самостоятельно пройти путь от сигнала к технической причине и при необходимости вернуться к материалам.
В итоге получается достаточно гибкий ритм: одно основное занятие в неделю + практика, которую можно распределить по нескольким дням. На обучение нужно выделять время, но для этого не требуется освобождать целый день или несколько вечеров подряд.
Полностью свободного периода для обучения можно ждать долго: после одной рабочей задачи обычно появляется следующая. Поэтому ориентироваться лучше не на идеальную неделю без дедлайнов, а на возможность регулярно выделять несколько небольших блоков на обучение.
Если такой ресурс сейчас есть, откладывать курс только в ожидании более спокойного графика необязательно.
⚡Третий поток Observability стартует 5 октября
Для тех, кто уже учился в Balun Courses, действует скидка:
• после 1 курса – 10%
• после 3+ курсов – 20%
• после 5+ курсов – 30%
Также обучение можно оплатить в рассрочку без процентов.
➡️ ПОСМОТРЕТЬ ПРОГРАММУ И ЗАПИСАТЬСЯ | 213 |
| 11 | Медленный запрос можно ускорить, не добавив ни одного индекса
Когда запрос начинает тормозить, очень легко сразу уйти смотреть индексы.
Хотя иногда проблема вообще не там.
Допустим, нужно получить пользователей, у которых больше пяти оплаченных заказов:
SELECT
u.id,
u.email,
(
SELECT COUNT(*)
FROM orders o
WHERE o.user_id = u.id
AND o.status = 'paid'
) AS paid_orders
FROM users u
WHERE (
SELECT COUNT(*)
FROM orders o
WHERE o.user_id = u.id
AND o.status = 'paid'
) > 5;
Сам по себе запрос выглядит вполне нормально: посчитали оплаченные заказы, потом оставили нужных пользователей.
А теперь открываем EXPLAIN ANALYZE.
PostgreSQL идёт по users и для каждой строки снова лезет в orders, чтобы выполнить подзапрос. Причём COUNT(*) у нас фигурирует дважды — и для фильтрации, и для результата.
Если в users 50 000 строк, это уже совсем другая история.
Упрощённо план может выглядеть так:
Seq Scan on users
Filter: (SubPlan > 5)
SubPlan
Aggregate
-> Seq Scan on orders
Filter: user_id = users.id
Здесь легко зацепиться глазами за Seq Scan и решить, что срочно нужен индекс.
Я бы сначала посмотрел на loops.
Если подзапрос выполняется десятки тысяч раз, база делает огромный объём повторной работы. Можно поставить индекс на orders.user_id, и каждый отдельный поиск станет дешевле. Но запрос от этого не перестанет снова и снова считать одно и то же.
Перепишем его:
WITH paid_orders AS (
SELECT
user_id,
COUNT(*) AS cnt
FROM orders
WHERE status = 'paid'
GROUP BY user_id
)
SELECT
u.id,
u.email,
p.cnt AS paid_orders
FROM paid_orders p
JOIN users u ON u.id = p.user_id
WHERE p.cnt > 5;
Теперь orders можно обработать один раз: отфильтровать оплаченные заказы, посчитать их по пользователям и дальше соединить уже агрегированный результат с users.
План будет выглядеть примерно так:
Hash Join
-> Seq Scan on users
-> Hash
-> HashAggregate
Group Key: orders.user_id
-> Seq Scan on orders
Filter: status = 'paid'
И да, Seq Scan всё ещё на месте.
Только теперь он выполняется в совсем другом контексте: вместо тысяч повторных проходов по orders — один проход и дальнейшая работа с уже посчитанными данными.
Поэтому сам факт, что в плане есть Seq Scan, ещё мало о чём говорит. Гораздо полезнее смотреть, сколько строк проходит через узлы, сколько раз они выполняются и где PostgreSQL делает работу повторно.
На курсе по PostgreSQL будет отдельная практика на таких задачах: пять медленных запросов нужно будет ускорить без добавления индексов и потом сравнить планы до и после. | 264 |
| 12 | پیام ویدیو | 153 |
| 13 | Как устроено задание по поиску причины деградации
Пример задания: В 14:00 p99 latency вырос в 20 раз. Ошибок в логах нет. Ваша задача — пройти по цепочке от алерта в Grafana через OpenTelemetry-трейсы прямо к строке кода или SQL-запросу, создающему блокировку.
Участник получает дашборд с каскадной деградацией сервисов, распределённый трейс и симулятор нагрузки, который воспроизводит проблемный сценарий.
Расследование начинается с алерта в Grafana. Дальше нужно перейти к OpenTelemetry-трейсам, определить span, на котором сосредоточена основная задержка, и продолжить поиск уже внутри конкретного участка - до строки кода или SQL-запроса, с которым связана деградация.
Смысл задания не в том, чтобы ещё раз настроить Grafana или трейсинг. Участник использует собранные данные последовательно: сначала замечает отклонение, затем сужает область поиска и проверяет возможную техническую причину.
После самостоятельной попытки можно свериться с ответом, где указано, что именно было сломано. При этом в материалах есть рекомендация не открывать его сразу, а сначала пройти расследование самостоятельно.
Так на практике отрабатывается путь от симптома к root cause analysis. По мере курса работа с отдельными сигналами переходит к анализу деградаций в системе из нескольких сервисов - метрики, логи и трейсы становятся инструментами одного расследования.
Такие задачи - часть практики курса Observability: работа с инструментами здесь привязана к конкретной инженерной задаче - понять состояние системы и последовательно искать причину проблемы.
🗓Третий поток стартует 5 октября.
⚡Через два дня будет финальное повышение цены. Если хотите зафиксировать текущую стоимость, но оплатить весь курс позже, можно внести бронь 5 000 ₽ - место и цена сохранятся за вами ❤️
➡️ Посмотреть программу курса Observability | 283 |
| 14 | ⚡️Уже завтра, 26 сентября, проведём бесплатную онлайн-конференцию для backend-разработчиков #РАЗНЕСИ_СОБЕС
В программе – 8 докладов с разбором конкретных вопросов, которые могут встретиться на технических собеседованиях в 2026 году. В каждом разберём отдельную тему: что спрашивают интервьюеры, какие знания проверяют и как обосновать свой ответ.
Вы сможете освежить теорию и разобраться в инженерной логике решений, чтобы на собеседовании объяснять ход своих мыслей и отвечать на уточняющие вопросы.
🎁 Всем участникам будут доступны запись и конспект конференции. А среди тех, кто присоединится онлайн, разыграем mock-собеседование от it-interview.io и два места на любой курс или интенсив нашей школы.
✔️Зарегистрироваться на конференцию | 234 |
| 15 | Prometheus, Grafana и Loki: от данных к диагностике
В Grafana виден рост процента ошибок API. Метрики поступают в Prometheus, логи доступны в Loki, алерт сработал. Инфраструктура выполняет свои задачи, но команда еще должна определить, какие операции затронуты, где возникла проблема и какие данные помогут проверить возможную причину.
На общей панели отображается процент ошибок всего API. Он позволяет обнаружить отклонение от нормы, но не показывает, как ошибки распределены между операциями. Для дальнейшего анализа потребуется детализация: какие эндпоинты затронуты, как изменились их показатели и совпадает ли рост ошибок с изменением нагрузки.
Здесь имеет значение не только наличие метрик, но и то, какие вопросы позволяют исследовать запросы и дашборды. Если нужная детализация не предусмотрена, установленный Prometheus сам по себе ее не обеспечит.
Дальше команда переходит к расследованию. В Loki могут храниться логи всех сервисов за интересующий период, но совпадение по времени еще не означает, что каждая найденная ошибка связана с обнаруженной деградацией. Нужно выделить релевантные события, проверить зависимости и, если операция проходит через несколько сервисов, восстановить ее путь по распределенным трейсам.
Для этого необходимо заранее продумать, как диагностические данные будут использоваться совместно. Наличие отдельных инструментов еще не гарантирует, что между обнаруженным симптомом и данными для расследования можно быстро установить связь.
Та же логика относится к алертингу. Уведомление должно помогать команде оценить значимость отклонения и определить дальнейшие действия. Иначе после срабатывания алерта инженеру приходится самостоятельно выяснять, какие показатели проверять и где искать дополнительные сведения.
Качество наблюдаемости определяется в том числе тем, какие вопросы о состоянии системы позволяют исследовать собранные данные и насколько они помогают команде принимать решения.
На курсе Observability эти задачи разбираются последовательно: участники проектируют метрики и запросы, строят дашборды, настраивают алертинг, учатся связывать логи и трейсы и анализировать деградации в системе из нескольких сервисов
В результате отдельные инструменты и сигналы складываются в подход, который помогает последовательно переходить от обнаруженного отклонения к поиску его причины. | 237 |
| 16 | Создали индекс, чтобы ускорить чтение. В итоге база стала работать медленнее
Запрос выполнялся 800 мс. После добавления индекса – 20 мс. Вроде бы всё отлично. Метрика улучшилась в 40 раз, задачу можно закрывать.
Через пару недель выясняется, что INSERT стал тяжелее, массовые UPDATE тоже просели, а индексы на таблице уже занимают приличный объём) И оптимизация, которая выглядела очевидно успешной, внезапно перестаёт быть такой однозначной 😁
Возьмём обычную таблицу orders. В неё постоянно добавляются новые заказы, меняются статусы, обновляется информация об оплате. На таблице уже есть несколько индексов, потом появляется ещё один – ради того самого медленного SELECT.
С чтением всё хорошо. А вот при каждой вставке PostgreSQL теперь приходится обновлять ещё одну индексную структуру. И чем больше индексов висит на активно изменяемой таблице, тем дороже обходится запись...
С UPDATE ещё интереснее. PostgreSQL из-за MVCC создаёт новую версию строки. Если изменившаяся колонка входит в индекс, индекс тоже приходится обновлять. А если часто изменяемое поле проиндексировано, для такого изменения уже не получится использовать HOT update.
Плюс индекс нужно хранить на диске и обслуживать. На одной маленькой таблице это может быть вообще незаметно. На большой write-heavy таблице – уже нет.
Допустим, запрос, который мы ускорили, выполняется 200 раз в минуту. А INSERT и UPDATE по этой же таблице – 20 000 раз.
После этого цифры 800 мс → 20 мс выглядят уже чуть иначе.
Поэтому перед созданием индекса я бы сначала посмотрел, как вообще живёт эта таблица: сколько на ней чтения и записи, какие индексы уже есть, насколько дорог конкретный запрос и как часто он реально выполняется. Иногда новый индекс действительно оправдан. Иногда дешевле переписать запрос. А бывает, что нужный индекс уже существует, просто PostgreSQL по какой-то причине его не выбирает 🤷♂️
На курсе по PostgreSQL как раз будем разбирать индексы на таких кейсах: смотреть на запрос и нагрузку, выбирать решение и потом проверять по EXPLAIN, что изменилось до и после. | 244 |
| 17 | Что должен заложить backend-разработчик, если мониторингом занимается другая команда
При разработке нового эндпоинта нужно решить, как отличать ожидаемый отказ по правилам продукта от технического сбоя. Если сбор и хранение телеметрии поддерживает другая команда, кто определит, какие события считать и что записывать в логи?
В разных компаниях задачи backend, DevOps и SRE распределены по-разному. Прикладные сигналы стоит проектировать вместе с разработчиками сервиса: для этого нужно знать логику операций и условия их выполнения.
📋Вот что полезно согласовать до релиза:
✔️Смысл метрик.
Определите, что считается успешным выполнением, ожидаемым отказом и технической ошибкой. Если есть повторные попытки, явно обозначьте, считает метрика отдельные попытки или операции целиком: эти значения отвечают на разные вопросы.
✔️Точки инструментирования.
Проверьте, какие этапы обработки уже видны в телеметрии. Если важный участок прикладной логики не измеряется отдельно, можно добавить span или метрику длительности. Выбор зависит от того, какой вопрос о работе этого участка нужно исследовать.
✔️Состав логов и диагностический контекст.
Согласуйте поля для типа операции, ее результата и категории ошибки, чтобы записи можно было последовательно фильтровать. Request ID помогает находить связанные события, а trace ID в записи - сопоставлять ее с трейсом. Нужный контекст должен быть доступен в тех местах кода, где создаются эти записи.
✔️Ограничения на данные.
Уникальный request ID не стоит добавлять в labels метрик Prometheus: каждая новая комбинация значений меток создаёт отдельный временной ряд и увеличивает расход ресурсов. Состав логов тоже требует проверки - пароли и токены доступа нужно исключить из записей.
Эти решения определяют, какие данные получит команда для диагностики после релиза. На курсе Observability эта работа входит в практику с Go-приложением: вы создаете и экспортируете собственные метрики, настраиваете структурированное логирование, интегрируете OpenTelemetry и анализируете задержки и ошибки по трейсам.
Такая практика полезна backend-разработчику и при готовой инфраструктуре мониторинга: она помогает связать решения в коде с возможностями расследования. Посмотрите программу курса Observability, чтобы оценить, какие из этих задач вам нужно отработать. | 266 |
| 18 | پیام ویدیو | 268 |
| 19 | پیام ویدیو | 261 |
| 20 | پیام ویدیو | 261 |
