RUEN

Неделя 126. Рентген для системы

Неделя 126. Рентген для системы

Разбор этой статьи

AI-подкаст BotsellerНеделя 126. Рентген для системы
0:00 / 0:00

Эту тему разобрали в подкасте. Слушай параллельно с чтением.

Это новогодняя неделя. 29 декабря 2025 года, понедельник. До Нового года два дня, до первого рабочего дня страны - неделя. А мы пишем код.

Сейчас, зная будущее, я понимаю: именно на этой неделе мы построили инструменты, которые через семь дней спасут нас от катастрофы. Но тогда мы об этом не думали. Мы просто решали задачи, которые давно откладывали.

115 записей разработки за неделю. 5 рабочих контуров. Два больших направления: наблюдаемость системы и CRM для детского центра. И одно маленькое решение, которое задним числом оказалось самым важным за весь декабрь.

Зачем работать в новогоднюю неделю

У этой недели есть контекст, без которого непонятно, почему мы вообще что-то делали между ёлкой и оливье.

Правило тихой недели: 115 записей разработки, 5 рабочих контуров. Инфраструктурные изменения нужно делать, когда система спокойна.

К концу декабря 2025-го Botseller был живым продуктом с реальными клиентами. Один из них - детский центр, который пришёл к нам со своей спецификой: расписание занятий, абонементы, филиалы, запись детей на группы. CRM, которую мы строили для переписок и продаж, должна была научиться работать с совершенно другим типом бизнеса.

А параллельно накопился технический долг по наблюдаемости. Система работала, но мы не всегда видели, что внутри. Логи были, но без связи между сервисами. Один запрос проходил через пять микросервисов, а понять путь от начала до конца было невозможно. Каждый сервис писал свою историю, не зная про остальные.

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

Развилка была простой. Отдохнуть и начать в январе. Или использовать тихую неделю для работы, которую опасно делать под нагрузкой. Мы выбрали второе. И, как показала следующая неделя, это было одним из лучших решений года.

Рентген для пяти сервисов за одну ночь

29 декабря, пока страна готовилась к празднику, мы раскатывали распределённую трассировку.

Слепая зона из пяти микросервисов: система работала, но мы угадывали контекст по меткам времени. Понять путь запроса от начала до конца было невозможно.

Суть простая: каждый запрос в систему получает уникальный идентификатор. Этот идентификатор проходит через все сервисы, которые запрос затрагивает. В логах каждого сервиса этот идентификатор остаётся как маркер.

Раньше, если что-то ломалось, мы открывали логи одного сервиса, видели ошибку, но не понимали контекст. Какой запрос вызвал ошибку? Что происходило в других сервисах в этот момент? Сколько времени заняла каждая часть? Ответов не было. Мы угадывали по меткам времени.

Распределённая трассировка за одну ночь: уникальный ID присваивается на старте, прошивается через все сервисы, базы данных и фоновые задачи.

После раскатки картина изменилась. Один идентификатор связывал все шаги: вошёл запрос, обработался в одном сервисе, ушёл в другой, достал данные из базы, вернул ответ. Если что-то тормозило, мы видели, где именно. Если падало, мы видели, на каком шаге.

Важная деталь: мы не просто включили трассировку, а сделали это одновременно во всех пяти активных сервисах. Это было принципиально. Трассировка в одном сервисе без остальных - как рентген одной руки, когда болит весь скелет. Ценность появляется, когда видна вся цепочка.

Трассировка работает только везде: иллюзия контроля (1 из 5) против правила полного рентгена (100%).

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

Зная будущее, я могу сказать: именно эта трассировка через семь дней помогла нам понять масштаб CASCADE-инцидента, когда одна команда стёрла 700 тысяч записей. Без неё мы бы восстанавливались вслепую.

Профилирование: не только что сломалось, но и что тормозит

3 января мы добавили непрерывное профилирование. Это другой инструмент, чем трассировка.

Инструменты наблюдаемости: распределённая трассировка показывает путь запроса через систему, непрерывное профилирование показывает, на что процессор тратит время внутри сервиса.

Трассировка показывает путь запроса. Профилирование показывает, на что процессор тратит время.

Зачем это нужно. Система может работать без ошибок, но медленно. Пользователь жмёт кнопку, ждёт три секунды, получает результат. Ошибки нет, всё «работает». Но три секунды - это плохо. Профилирование показывает, какая функция, какой кусок логики, какая операция с базой съедает эти три секунды. Без этого инструмента оптимизация превращается в угадывание.

Мы добавили его в два сервиса: CRM и хранилище данных. Управление через переменную окружения: включил, посмотрел, выключил. Без влияния на рабочую нагрузку, когда не нужно.

Забегая вперёд: этот инструмент пригодился, когда CRM начала расти и мы искали узкие места в запросах к базе.

Детский центр: когда CRM учится новой профессии

Вторая большая линия недели - работа для конкретного клиента. Детский центр с филиалами, расписанием, групповыми занятиями, абонементами и записью детей.

Эволюция CRM: от модели «переписка и воронка продаж» к модели «запись на занятие» с расписанием, групповыми занятиями, абонементами и филиалами.

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

За неделю мы сделали несколько вещей. Записи на занятия через API и интерфейс. Абонементы с учётом остатка визитов. Удаление записи с возвратом визита в абонемент. Привязку занятий к филиалам. Защиту от наложения слотов в расписании. Возрастные ограничения на дату занятия.

Защита от наложения слотов: ребёнок не может быть в двух местах одновременно. Система блокирует запись на рисование и бассейн в одно время.

И одну валидацию, которая мне нравится больше всего: ребёнок не может быть записан на два занятия одновременно. Звучит очевидно. Но пока система не проверяет это сама, администратор детского центра может случайно записать Катю на рисование и плавание в одно время. Мама придёт и спросит, как Катя будет рисовать в бассейне.

Интерфейс тоже двигался: фильтрация по родителям, история посещений, отображение заполненности группы в расписании, кнопки удаления абонементов, исправление формата дат. Много мелкой, но нужной работы, которая превращает таблицу с данными в рабочее место администратора.

Маленькая деталь: Python 3.14 не прошёл проверку

Культура инженерии: откат без драмы. Попробовали Python 3.14, зависимости упали, откатили на 3.12 за один час. Рабочий продукт всегда важнее красивого номера версии.

Одна строчка в логе, за которой стоит решение. Мы попробовали Python 3.14 на одном из сервисов. Не получилось: часть зависимостей не поддерживала новую версию. Откатили на 3.12.

Зачем рассказываю. Потому что это нормальный процесс. В стартапе всегда есть соблазн быть на последней версии всего. Но рабочий продукт важнее красивого номера версии. Мы попробовали, не получилось, откатили. Потратили час, а не день. Это и есть инженерная зрелость: пробовать быстро, откатывать без драмы.

Урок недели: инвестируй в наблюдаемость до того, как она понадобится

Сейчас, в 2026 году, я вижу неделю 126 как одну из самых важных для инфраструктуры Botseller. Не по количеству фич, а по тому, что она дала фундамент для всех будущих инцидентов и оптимизаций.

Фундамент выживания: три правила наблюдаемости. Правило тихой недели, правило полного рентгена, правило заблаговременности. На пересечении - системная зрелость.

Фреймворк, который я из неё вынес:

Правило тихой недели. Инфраструктурные изменения нужно делать, когда система спокойна. Новогодняя неделя, выходные, период низкой нагрузки. Это не лень и не прокрастинация. Это единственное безопасное окно для работы, которая трогает всё сразу.

Правило полного рентгена. Наблюдаемость работает только когда она везде. Трассировка в одном сервисе из пяти - это не трассировка, это иллюзия контроля. Либо раскатываешь на всё, либо не начинаешь.

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

Если вы строите продукт и ещё не видите, что происходит внутри: не ждите инцидента. Постройте рентген сейчас, пока ничего не болит.

Что дальше

Неделя 127: удар CASCADE. Одна команда TRUNCATE с каскадным удалением стирает 700 тысяч записей на проде. Рентген, развёрнутый на неделе 126, показал масштаб разрушений мгновенно.

Следующая неделя - 127. CASCADE. Один TRUNCATE с каскадным удалением стирает 700 тысяч записей на проде. Мы уже рассказали эту историю в предыдущем выпуске. Но теперь вы знаете, что трассировка, которая помогла нам в тот день, была развёрнута ровно за неделю до этого.

Постройте рентген сейчас, пока ничего не болит. Иногда лучшая подготовка к катастрофе - это просто сделать свою инфраструктурную работу вовремя.

Иногда лучшая подготовка к катастрофе - это просто делать свою работу вовремя.

FAQ

Почему команда работала в новогоднюю неделю?

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

Что такое распределённая трассировка и зачем она нужна?

Это способ проследить путь одного запроса через все сервисы системы. Каждый запрос получает уникальный идентификатор, который остаётся в логах каждого сервиса. Если что-то сломалось или тормозит, видно где именно.

Зачем CRM для продаж занятия и расписание?

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

Чем профилирование отличается от трассировки?

Трассировка показывает путь запроса через систему. Профилирование показывает, на что именно процессор тратит время внутри каждого сервиса. Первое отвечает на вопрос «где запрос был», второе - «почему он был там так долго».

Почему откатили Python 3.14 обратно на 3.12?

Часть зависимостей не поддерживала новую версию. Рабочий продукт важнее красивого номера версии. Попробовали, не получилось, откатили за час.

Правда ли, что трассировка помогла при CASCADE-инциденте?

Да. Распределённая трассировка, развёрнутая на неделе 126, помогла понять масштаб инцидента на неделе 127, когда каскадное удаление стёрло 700 тысяч записей. Без неё восстановление заняло бы значительно больше времени.