>_ Hello World Приветствую!
Меня зовут Алексей. Я Backend разработчик с 6 годами опыта, последние 1.5 года руковожу командой в позиции Team Lead
За это время я побывал в разных ролях — от активного участника и инициатора технических обсуждений и решений до наблюдателя за тем, как формируются и развиваются решения в командах. Эта комбинация наделила меня ценным опытом и пониманием работы процессов.
Когда я только начинал свой путь в IT, меня вдохновляла и мотивировала возможности учиться абсолютно бесплатно. Главное - вовлеченность, горящие глаза и время. Индустрия дала мне все необходимое, чтобы строить свою карьеру: от решений редких кейсов в дальних углах интернета до ответов опытных коллег на StackOverflow и Habr. Буду постепенно выкладывать застоявщиеся мысли, оформлять их в посты и делиться с вами. Рассказывать об опыте построение карьеры в IT. И параллельно с вами учиться новому
На этом канале я буду писать о том, что считаю важным для инженеров и лидеров:
• Архитектура Backend: устойчивость и нагрузка
• Управление командами и процессами
• Развитие хард- и софт-скиллов в IT
• Практические разборы из своей работы
• Использование AI в командах, процессах и продуктах
Канал будет авторским, живым и максимально полезным для всех, кто в IT.
Подписывайтесь - впереди много интересного!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3⚡2😁2💯2🤯1
Серии постов:
Django Blue Green:
- Blue Green №1
- Blue Green №2
- Blue Green №3
Saga Pattern:
- Saga №1
- Saga №2
- Saga №3
Django Blue Green:
- Blue Green №1
- Blue Green №2
- Blue Green №3
Saga Pattern:
- Saga №1
- Saga №2
- Saga №3
✍1👍1🤔1🤯1
Буду постепенно запускать серии постов, наполняя контентом этот канал и параллельно изучая механизмы навигации между постами в Телеграм. Начну с темы, по которой сейчас веду работы подготовки к докладу Moscow Python MeetUp - Django Blue Green Deployment
В серии постов я хочу рассказать, как мы внедряем BG в большой Django-монолит, какие ограничения упираются в СУБД, какие в процессы, а какие вообще в Django. И о том, как мы постепенно решаем эти проблемы...
• Как всё началось:
Летом 2023 года один релиз прошёл настолько плохо, что мы впервые всерьёз задумались о полноценном механизме отказоустойчивых релизов. Основная боль быстро стала очевидной: сложные изменения схемы БД делают откат болезненным и иногда невозможным, особенно когда релиз сопровождается миграциями.
Мы сравнили канареечные релизы и BG. Для нас критичным было быстрое переключение между окружениями — значит BG.
И сразу столкнулись о главный вопрос:
- Как поддерживать две версии кода с разными моделями в БД, при этом имея всего одну БД?
• Идея:
Мы решили, что схема БД должна временно удовлетворять требованиям _обоих_ окружений. Для этого стандартные Django-команды
Все миграции мы классифицировали на три группы:
- Конструктивные
(
— те, что расширяют схему и безопасны для обеих версий кода.
- Деструктивные
(
— операции, которые ломают совместимость.
- Невозможные для BG
(
— операции, при которых единая схема не может одновременно поддерживать обе версии.
На этапе Blue мы выполняем только конструктивные миграции — так новая версия получает всё, что ей нужно, а старая продолжает работать.
После успешного релиза и наблюдения за стабильностью — запускаем Green, где выполняется деструктивная часть. С этого момента откат на прошлую версию уже рискован, но и не нужен.
В следующих постах я покажу техническую сторону — как мы адаптировали DevOps-процессы, патчили Django и перестраивали миграции под две фазы. Если вам интересна инженерная кухня BG на большом монолите — будет полезно.
Blue-Green деплоймент — это подход, который позволяет выкатывать новую версию сервиса без простоя и риска «положить» прод. Суть проста: одновременно существует два окружения — Blue и Green. Одно обслуживает пользователей, другое — готовится к релизу. В нужный момент трафик переключается между ними.
В серии постов я хочу рассказать, как мы внедряем BG в большой Django-монолит, какие ограничения упираются в СУБД, какие в процессы, а какие вообще в Django. И о том, как мы постепенно решаем эти проблемы...
• Как всё началось:
Летом 2023 года один релиз прошёл настолько плохо, что мы впервые всерьёз задумались о полноценном механизме отказоустойчивых релизов. Основная боль быстро стала очевидной: сложные изменения схемы БД делают откат болезненным и иногда невозможным, особенно когда релиз сопровождается миграциями.
Мы сравнили канареечные релизы и BG. Для нас критичным было быстрое переключение между окружениями — значит BG.
И сразу столкнулись о главный вопрос:
- Как поддерживать две версии кода с разными моделями в БД, при этом имея всего одну БД?
• Идея:
Мы решили, что схема БД должна временно удовлетворять требованиям _обоих_ окружений. Для этого стандартные Django-команды
makemigrations и migrate мы разделили на две фазы — Blue и Green.Все миграции мы классифицировали на три группы:
- Конструктивные
(
CreateModel, AddField, AddConstraint, AddIndex) — те, что расширяют схему и безопасны для обеих версий кода.
- Деструктивные
(
RemoveField, DeleteModel и т.п.) — операции, которые ломают совместимость.
- Невозможные для BG
(
AlterField, критичные AlterTable и т.п.) — операции, при которых единая схема не может одновременно поддерживать обе версии.
На этапе Blue мы выполняем только конструктивные миграции — так новая версия получает всё, что ей нужно, а старая продолжает работать.
После успешного релиза и наблюдения за стабильностью — запускаем Green, где выполняется деструктивная часть. С этого момента откат на прошлую версию уже рискован, но и не нужен.
В следующих постах я покажу техническую сторону — как мы адаптировали DevOps-процессы, патчили Django и перестраивали миграции под две фазы. Если вам интересна инженерная кухня BG на большом монолите — будет полезно.
❤1🤔1🤯1💯1
Всем привет! Начинаю заметки о том, как мы работаем над архитектурными практиками в компании - как принимаем технические решения на уровне компании, и чем чреват локальный подход к разработке. В этом посте — про то, как у нас появились архитектурные комитеты и ADR.
➡️ Зачем это вообще понадобилось
Пока компания росла, а команды формировались - долгое время казалось, что каждая фича локальна и живёт внутри своего проекта. На практике изменения в данных и API тихо расходились между сервисами, и проблемы всё чаще всплывали на стыках.
Самым болезненным симптомом оказалось дублирование доменных сущностей. Каждая продуктовая команда, не осознавая этого, начинала хранить «свою» версию данных — с локальными особенностями и логикой. В итоге любая небольшая фича, требующая интеграции между командами, переставала быть маленькой: сроки растягивались из дней и недель в месяцы.
В какой-то момент стало понятно: проблема не в конкретных решениях, а в отсутствии общего архитектурного контура.
ℹ️ Появление архитектора как точки перелома
Изначально архитектор подключился к компании для взращивания технических лидов. Лиды приходили к нему с болями в проектах, мы разбирали контекст, собирали мини-дорожные карты улучшений и уходили их прорабатывать.
Со временем на эти сессии начали приходить и разработчики — уже с конкретными фичами и архитектурными вопросами. Стало ясно, что обсуждать решения заранее — полезно, но делать это в произвольном формате сложно масштабировать. Нужен был общий, понятный всем шаблон обсуждения.
Так у нас и появился формат ADR.
ℹ️ Что такое ADR у нас
ADR (Architecture Decision Records) — это единый формат, который позволяет быстро погрузить всех участников архитектурного комитета в контекст обсуждаемой проблемыю
Важно: для нас ADR — это не столько документ, сколько процесс согласования архитектурных изменений
Комитет собирается два раза в неделю, встречи длятся 1...3 часа в зависимости от количества тем. Участвуют разработчики, лиды, архитектор, CTO — все, кому интересно обсудить проблему, важно найти решение.
↗️ Почему это оказалось полезным
Появилось одно место, где архитектура предприятия складывается в общую картину, а не остаётся набором локальных решений. Появились общие практики и точка истинности для архитектурных договорённостей.
Но лично для меня самое ценное — это то, что у нас появилось пространство, где мы регулярно и открыто обсуждаем технологии, ограничения, спорим, брейнштормим, экспериментируем на ходу и подсвечиваем друг другу зоны роста. В какой-то момент архитектура перестает быть чьей-то ролью и становится общим процессом - и это, пожалуй, главный признак зрелости.
Позже сделаю пост о том, как появление архитектурных комитетов отразилось на архитектурной зрелости нашего предприятия:
Хороший материал по этой теме
Теги: #ADR
➡️ Зачем это вообще понадобилось
Пока компания росла, а команды формировались - долгое время казалось, что каждая фича локальна и живёт внутри своего проекта. На практике изменения в данных и API тихо расходились между сервисами, и проблемы всё чаще всплывали на стыках.
Самым болезненным симптомом оказалось дублирование доменных сущностей. Каждая продуктовая команда, не осознавая этого, начинала хранить «свою» версию данных — с локальными особенностями и логикой. В итоге любая небольшая фича, требующая интеграции между командами, переставала быть маленькой: сроки растягивались из дней и недель в месяцы.
В какой-то момент стало понятно: проблема не в конкретных решениях, а в отсутствии общего архитектурного контура.
ℹ️ Появление архитектора как точки перелома
Изначально архитектор подключился к компании для взращивания технических лидов. Лиды приходили к нему с болями в проектах, мы разбирали контекст, собирали мини-дорожные карты улучшений и уходили их прорабатывать.
Со временем на эти сессии начали приходить и разработчики — уже с конкретными фичами и архитектурными вопросами. Стало ясно, что обсуждать решения заранее — полезно, но делать это в произвольном формате сложно масштабировать. Нужен был общий, понятный всем шаблон обсуждения.
Так у нас и появился формат ADR.
ℹ️ Что такое ADR у нас
ADR (Architecture Decision Records) — это единый формат, который позволяет быстро погрузить всех участников архитектурного комитета в контекст обсуждаемой проблемыю
Важно: для нас ADR — это не столько документ, сколько процесс согласования архитектурных изменений
• Команда приносит контекст проблемы, варианты решений и ограничения системы
• Вместе обсуждаем риски и влияние на другие сервисы
• Фиксируем контракт изменений и итоговое решение
Комитет собирается два раза в неделю, встречи длятся 1...3 часа в зависимости от количества тем. Участвуют разработчики, лиды, архитектор, CTO — все, кому интересно обсудить проблему, важно найти решение.
↗️ Почему это оказалось полезным
Появилось одно место, где архитектура предприятия складывается в общую картину, а не остаётся набором локальных решений. Появились общие практики и точка истинности для архитектурных договорённостей.
Но лично для меня самое ценное — это то, что у нас появилось пространство, где мы регулярно и открыто обсуждаем технологии, ограничения, спорим, брейнштормим, экспериментируем на ходу и подсвечиваем друг другу зоны роста. В какой-то момент архитектура перестает быть чьей-то ролью и становится общим процессом - и это, пожалуй, главный признак зрелости.
Позже сделаю пост о том, как появление архитектурных комитетов отразилось на архитектурной зрелости нашего предприятия:
Хороший материал по этой теме
Теги: #ADR
❤1🤯1💯1
Всем привет! Продолжаю серию постов про Blue Green Django Deployment
В этом посте хочу разобрать, из каких этапов реально состояла реализация BG - со стороны DevOps и со стороны разработки - и к каким выводам мы начали приходить ещё в процессе внедрения
1️⃣ Инфраструктура
Со стороны DevOps задача сначала выглядела относительно прямолинейно:
Но довольно быстро стало ясно, что application-core - не единственный участник релиза:
Во время деплоя мы также выкатываем набор сервисов, которые:
Поэтому, чтобы разрешить эту проблему пришлось:
В CI/CD это вылилось в раздельные пайплайны.
В итоге релиз-инженер не “деплоит”, а нажимает кнопку вида activate {color} - за которой стоит цепочка из 8–9 job, которые:
С точки зрения эксплуатации - огромный шаг вперёд.
С точки зрения Kubernetes -ничего магического, просто много аккуратной работы.
2️⃣ Django и двухфазные миграции
А вот со стороны разработки всё было сильно менее линейно.
Идея патчинга Django-механизма миграций сначала выглядела как чистый инженерный челлендж:
1. Написать команду, аналог
2. Пропатчить migrate, чтобы он принимал флаги
Технически это означало:
Немного сахара вокруг Django internals, немного monkey-patching’а —
и прототип действительно заработал
ℹ️ Но…
Чем дальше мы углублялись, тем отчётливее становилось несколько вещей:
Формально механизм работал. Фактически — мы начали:
⏸️ И в какой-то момент вопрос перестал быть техническим:
В следующем посте - момент, когда этот вопрос перестал быть философским
и стал причиной отказа от решения, в которое уже было вложено слишком много
В этом посте хочу разобрать, из каких этапов реально состояла реализация BG - со стороны DevOps и со стороны разработки - и к каким выводам мы начали приходить ещё в процессе внедрения
1️⃣ Инфраструктура
Со стороны DevOps задача сначала выглядела относительно прямолинейно:
• два полноценных prod-окружения: Blue и Green
• один ingress и переключение трафика «по кнопке»
• единая СУБД
• возможность деплоить и тестировать неактивное окружение независимо от активного
Но довольно быстро стало ясно, что application-core - не единственный участник релиза:
Во время деплоя мы также выкатываем набор сервисов, которые:
• шарят конфигурацию с монолитом
• имеют собственный lifecycle
• не должны перезапускаться синхронно с core
Поэтому, чтобы разрешить эту проблему пришлось:
• жёстко отделить core от сервисов
• описать их entrypoint.sh и поведение при старте/остановке
• сформировать правило:
- core деплоится отдельно и независимо от всех сервисов
В CI/CD это вылилось в раздельные пайплайны.
В итоге релиз-инженер не “деплоит”, а нажимает кнопку вида activate {color} - за которой стоит цепочка из 8–9 job, которые:
• Корректно завершают "shared resources"
• переключение ingress на новый application-core
• healthcheck
• И только потом: поочерёдный подъём зависимостей
С точки зрения эксплуатации - огромный шаг вперёд.
С точки зрения Kubernetes -ничего магического, просто много аккуратной работы.
2️⃣ Django и двухфазные миграции
А вот со стороны разработки всё было сильно менее линейно.
Идея патчинга Django-механизма миграций сначала выглядела как чистый инженерный челлендж:
1. Написать команду, аналог
makemigrations, которая делит миграции на Blue (конструктивные) и Green (деструктивные)2. Пропатчить migrate, чтобы он принимал флаги
migrate --blue / --green и выполнял отфильтрованный набор миграций Технически это означало:
• повторить большую часть логики makemigrations
• переопределить MigrationWriter → PatchedMigrationWriter
• на этапе записи миграции разделять операции
• добавить две стратегии:
- определение типа операции
- определение конкретной операции (с нюансами)
Немного сахара вокруг Django internals, немного monkey-patching’а —
и прототип действительно заработал
ℹ️ Но…
Чем дальше мы углублялись, тем отчётливее становилось несколько вещей:
• Django migration operations - это не контракт с СУБД, а декларация намерений
• одна и та же операция может транслироваться в SQL по-разному
• порядок операций иногда важнее их формального типа
• зависимости между миграциями начинают жить своей жизнью
Формально механизм работал. Фактически — мы начали:
• усложнять один из самых критичных участков фреймворка
• вводить вторую модель мышления поверх стандартных миграций
• перекладывать сложность с процесса на код
⏸️ И в какой-то момент вопрос перестал быть техническим:
Мы правда делаем систему надёжнее -
или просто строим очень умный костыль,
который однажды станет нашей главной точкой отказа?
В следующем посте - момент, когда этот вопрос перестал быть философским
и стал причиной отказа от решения, в которое уже было вложено слишком много
👍1😁1🤯1
Всем привет!
Этим постом запускаю серию про паттерн Saga - не в теории, а через реальный путь: от сломанной консистентности в распределенной системе до решения, поселившегося в продакшене. И к выводам, которые мы смогли вынести из этого опыта
В этой серии:
ℹ️ Контекст:
В начале было слово, и словом этим было VCard.
Так мы называем наш сервис виртуальной карты, который позволяет гостям пользоваться преимуществами программы лояльности при заказах в ресторанах.
Работает это так:
Пользовательский флоу элементарный.
Системный - нет
➡️ Решение “в лоб”:
Когда мы реализовывали этот флоу, о паттерне Saga мы ещё не знали.
Решение выглядело логично:
Никакой магии,
никакой надёжности,
никакой согласованности 🙂
🧪 Тестирование:
На тестовом стенде всё работало как надо! Иногда всплывали редкие аномалии - примерно один случай из ста.
Мы списывали это на:
Обвиняли что угодно, даже ретроградный Меркурий,
лишь бы не откладывать релиз нового пользовательского сервиса
🛑 Продакшен:
Продакшен очень быстро показал,
насколько сильно мы ошибались.
И за эту ошибку пришлось заплатить кратно
С ростом нагрузки редкие сбои
превратились в поток инцидентов
Стало совершенно ясно:
• это не единичные баги
• и не «особенности окружения»
❗️Это - системная проблема в реализации сервиса
⏯️ В следующий раз я расскажу:
• как мы начали разбирать эти инциденты
• какие закономерности нашли
• и почему в итоге упёрлись в вопрос консистентности
в распределенной системе
Этим постом запускаю серию про паттерн Saga - не в теории, а через реальный путь: от сломанной консистентности в распределенной системе до решения, поселившегося в продакшене. И к выводам, которые мы смогли вынести из этого опыта
В этой серии:
• как я вообще на него наткнулся
• почему «простые» решения перестают работать
• как сохранять консистентность в распределённых системах
ℹ️ Контекст:
В начале было слово, и словом этим было VCard.
Так мы называем наш сервис виртуальной карты, который позволяет гостям пользоваться преимуществами программы лояльности при заказах в ресторанах.
Работает это так:
• пользователь сканирует QR-код на столе
• видит заказ в мобильном приложении
• применяет карту - копит бонусы или списывает уже накопленные
Пользовательский флоу элементарный.
Системный - нет
➡️ Решение “в лоб”:
Когда мы реализовывали этот флоу, о паттерне Saga мы ещё не знали.
Решение выглядело логично:
• холдируем бонусы в CRM
• последовательно выполняем операции на кассе
• фиксируем результат
• при ошибке - откатываем все
Никакой магии,
никакой надёжности,
никакой согласованности 🙂
🧪 Тестирование:
На тестовом стенде всё работало как надо! Иногда всплывали редкие аномалии - примерно один случай из ста.
Мы списывали это на:
• ограниченные ресурсы стейджа
• нестабильность окружения
• тестовые данные
Обвиняли что угодно, даже ретроградный Меркурий,
лишь бы не откладывать релиз нового пользовательского сервиса
🛑 Продакшен:
Продакшен очень быстро показал,
насколько сильно мы ошибались.
И за эту ошибку пришлось заплатить кратно
С ростом нагрузки редкие сбои
превратились в поток инцидентов
Десятки тысяч заказов в день → около сотни недовольных пользователей ежедневно → десятки сходящих с ума специалистов тех.поддержки обрабатывающие обращения клиентов
Стало совершенно ясно:
• это не единичные баги
• и не «особенности окружения»
❗️Это - системная проблема в реализации сервиса
⏯️ В следующий раз я расскажу:
• как мы начали разбирать эти инциденты
• какие закономерности нашли
• и почему в итоге упёрлись в вопрос консистентности
в распределенной системе
❤1😁1🤯1
Продолжение серии статей про паттерн Saga. В прошлый раз мы остановились на том, что после релиза стало понятно - что проблема системная. И что проблема сама по себе никуда не денетеся. Но еще непонятно, в чем собственно проблема
❗️Инциденты повторялись.
❗️Поддержка тонула в обращениях.
❗️Поведение системы выглядело нестабильным и непредсказуемым.
Некоторое время мы пробовали фиксить конкретные баги, но это оказалось лишь лечением симптомов, что в итоге лишь усложяно систему, не решая системных проблем Мы перестали чинить отдельные баги и начали разбираться, что вообще происходит.
🔍 Что мы сделали:
И довольно быстро стало ясно - это не хаос. Все инциденты укладывались в несколько повторяющихся сценариев:
Сценарии разные, последствия разные - но эффект всегда один
❗️Нарушена консинстентность данных в системе
Система регулярно оказывалась в состоянии, когда часть шагов выполнена, а часть - нет
Мы не могли точно ответить:
❓ Ключевой вопрос:
В какой-то момент вопрос стал предельно конкретным:
С этим вопросом я пошёл искать ответы, тогда еще с поисковиком. Были же времена...
▶️ И тут появляется Saga
Через несколько статей я наткнулся на упоминание паттерна Saga, а затем — на его классическое описание на microservices.io
Saga предлагает смотреть на бизнес-операцию не как на одну транзакцию, а как на последовательность локальных шагов с описанием явных компенсирующими действий на каждом этапе
▶️ В следующих постах я расскажу:
• Как мы реализовывали Saga технически
• Почему выбрали режим оркестрации
• С какими граблями столкнулись в продакшене
❗️Инциденты повторялись.
❗️Поддержка тонула в обращениях.
❗️Поведение системы выглядело нестабильным и непредсказуемым.
Некоторое время мы пробовали фиксить конкретные баги, но это оказалось лишь лечением симптомов, что в итоге лишь усложяно систему, не решая системных проблем Мы перестали чинить отдельные баги и начали разбираться, что вообще происходит.
🔍 Что мы сделали:
• усилили логирование
• добавили трейсы
• начали группировать инциденты
И довольно быстро стало ясно - это не хаос. Все инциденты укладывались в несколько повторяющихся сценариев:
• Нарушение идемпотентности при слабой сети
• блокировка заказа операцией на кассе или официантом
• таймауты операций, когда касса нагружена
Сценарии разные, последствия разные - но эффект всегда один
❗️Нарушена консинстентность данных в системе
Система регулярно оказывалась в состоянии, когда часть шагов выполнена, а часть - нет
Мы не могли точно ответить:
• что сейчас происходит с заказом
• какие действия уже применены
• и что именно нужно откатить
❓ Ключевой вопрос:
В какой-то момент вопрос стал предельно конкретным:
Как сохранять консистентность в распределённой системе
без общей транзакции?
С этим вопросом я пошёл искать ответы, тогда еще с поисковиком. Были же времена...
▶️ И тут появляется Saga
Через несколько статей я наткнулся на упоминание паттерна Saga, а затем — на его классическое описание на microservices.io
Saga предлагает смотреть на бизнес-операцию не как на одну транзакцию, а как на последовательность локальных шагов с описанием явных компенсирующими действий на каждом этапе
▶️ В следующих постах я расскажу:
• Как мы реализовывали Saga технически
• Почему выбрали режим оркестрации
• С какими граблями столкнулись в продакшене
microservices.io
Microservices Pattern: Pattern: Saga
Implement transactions using a saga, which is sequence of local transactions
😁1🤔1🤯1🥴1
Заканчиваю серию постов про паттерн Saga. В прошлый раз я остановился на моменте, когда стало понятно, что без управления распределенной транзакцией проблему консистентности не решить.
В этом посте - подробнее о реализации Saga в системе
➡️ Выбор подхода:
Saga можно реализовать через:
• хореографию
• оркестрацию
В режиме оркестрации есть один объект, управляющий запуском этапов в разных системах.
В режиме хореографии системы сами определяют, когда и какой этап запустить.
Мы выбрали оркестрацию
Причины:
При этом сервис масштабируется горизонтально,
и управление шагами передаётся между инстансами через Kafka.
⚜️ Базовая идея реализации:
Главное ограничение - пользовательский флоу нельзя менять.
То есть имплементация Saga в проект должна быть бесшовной
Поэтому архитектура построена так:
Это позволило:
🧩 Типы Saga в системе:
В системе выделены три основных сценария:
• COMMIT - применение карты в заказ или досписание бонусов
• CANCEL - отмена применённой карты
• SUBSCRIBE - изменения заказа, инициированные кассой
Каждый сценарий разбит на атомарные шаги
с компенсирующими действиями: блокировка заказа, выполнение бизнес-условий в CRM и на кассе, разблокировка заказа
🛑 Broken Saga:
Если во время отката что-то пошло не так - Saga помечается как Broken
Дальше:
Это не идеальное решение, но понятное и лёгкое в поддержке.
🚨 Продакшен-грабли:
После релиза система работала стабильно.
Ровно до первого серьёзного пика нагрузки.
Из-за задержек на стороне кассовых демонов:
Проблему пришлось решать экстренно:
🔸 Усиливали демонов
🔸 Переезжали на новые топики
🔸 Принудительно откатывали активные Saga
После переработки флоу обработки Broken Saga эти проблемы нас больше не беспокоили.
✅ Итоги:
Saga не упростила систему. Она сделала её управляемой, но при этом значительно сложнее
Что изменилось:
🔹 Восстановилась консистентность
🔹 Пользовательский флоу стал стабильным
🔹 Поддержка перестала вручную разруливать зависшие списания
Новые баги появились, но теперь они локализованы внутри Saga, а не размазаны по всей системе.
🔄 Промежуточный вывод:
Я однозначно напишу отдельный пост-рефлексию об этом опыте, но, завершая серию, хочу зафиксировать:
В этом посте - подробнее о реализации Saga в системе
➡️ Выбор подхода:
Saga можно реализовать через:
• хореографию
• оркестрацию
В режиме оркестрации есть один объект, управляющий запуском этапов в разных системах.
В режиме хореографии системы сами определяют, когда и какой этап запустить.
Мы выбрали оркестрацию
Причины:
• сложная работа с кассовым оборудованием
• необходимость строгого контроля последовательности шагов
• таймауты, ретраи и явные переходы состояний
При этом сервис масштабируется горизонтально,
и управление шагами передаётся между инстансами через Kafka.
⚜️ Базовая идея реализации:
Главное ограничение - пользовательский флоу нельзя менять.
То есть имплементация Saga в проект должна быть бесшовной
Поэтому архитектура построена так:
• перед стартом Saga сохраняется копия заказа
• каждый шаг изменяет только копию
• основной заказ обновляется только после успешного завершения всех шагов
Это позволило:
• безопасно выполнять откаты
• избежать полусломанных состояний
• понимать текущее состояние транзакции
🧩 Типы Saga в системе:
В системе выделены три основных сценария:
• COMMIT - применение карты в заказ или досписание бонусов
• CANCEL - отмена применённой карты
• SUBSCRIBE - изменения заказа, инициированные кассой
Каждый сценарий разбит на атомарные шаги
с компенсирующими действиями: блокировка заказа, выполнение бизнес-условий в CRM и на кассе, разблокировка заказа
🛑 Broken Saga:
Если во время отката что-то пошло не так - Saga помечается как Broken
Дальше:
• сага уходит в фоновую обработку
• выполняются повторные попытки отката
• при неудаче требуется ручное вмешательство
Это не идеальное решение, но понятное и лёгкое в поддержке.
🚨 Продакшен-грабли:
После релиза система работала стабильно.
Ровно до первого серьёзного пика нагрузки.
Из-за задержек на стороне кассовых демонов:
• шаги перестали укладываться в TTL
• Saga начали падать на этапе блокировки заказа
• для обработки Broken Saga первый шаг всё ещё пытался заблокировать заказ
• задержка на кассе спровоцировала лавинообразное создание саг, приведя систему к отказу
• в отдельных случаях на один заказ создавались сотни Saga
Проблему пришлось решать экстренно:
🔸 Усиливали демонов
🔸 Переезжали на новые топики
🔸 Принудительно откатывали активные Saga
После переработки флоу обработки Broken Saga эти проблемы нас больше не беспокоили.
✅ Итоги:
Saga не упростила систему. Она сделала её управляемой, но при этом значительно сложнее
Что изменилось:
🔹 Восстановилась консистентность
🔹 Пользовательский флоу стал стабильным
🔹 Поддержка перестала вручную разруливать зависшие списания
Новые баги появились, но теперь они локализованы внутри Saga, а не размазаны по всей системе.
🔄 Промежуточный вывод:
Я однозначно напишу отдельный пост-рефлексию об этом опыте, но, завершая серию, хочу зафиксировать:
Saga свою задачу решила - она позволила взять под контроль состояния системы и управлять откатами на разных этапах. Однако цена этого решения оказалась высокой: архитектура усложнилась, требования к поддержке выросли, а жесткий контракт, сформированный уже после выхода в продакшен, заметно ограничил дальнейшее развитие сервиса.
👍3💯3❤2🤯1🥴1
Вот уже третий год подряд в первых числах января я иду покупать себе дневник - датированный ежедневник
Первый дневник, в 2024 году, я купил по простой причине: мысли перестали умещаться в голове. Их было много, структуры не было никакой. Работа, решения, ответственность, постоянный внутренний диалог - всё это не затихало ни на минуту. Мне нужно было место, куда я могу все это выгрузить
Так я и пришёл к своему первому дневнику
Я начал писать от руки - без формата, структуры и ожиданий. Просто выгружать бардак из головы
Уже через несколько месяцев, впервые перечитывая записи, я заметил сразу несколько вещей: у меня сформировалась привычка, появился свой формат, а вместе со структурой в письме - структура начала появляться в моей жизни
⏺️ Дополню: мне действительно нравится свобода своего формата письма. А еще мне нравится мой почерк - когда я не спешу, он доставляет мне почти эстетическое удовольствие. Это, безусловно, сыграло положительную роль для формирования привычки
Я продолжаю работать с дневниками уже третий год не потому, что это «просто полезная привычка», а потому что эффект от неё реально ощущается:
• письмо замедляет и приводит в состояние рефлексии,
• структура в записях постепенно переносится в решения и повседневность
• затих внутренний гомон, остался лишь один - голос, повторяющий... Так, стоп, это не сюда
ℹ️ Но главную ценность ведения дневника для себя я обнаружил в том же, в чем ее обнаруживали еще столетия назад наши предшественники:
Сила дневников в том, чтобы их перечитывать
Ты читаешь записи годовой давности и понимаешь: события ты помнишь, а вот себя в них - совсем нет. Эмоции кажутся чрезмерными, выводы - поспешными, уверенность - наивной.
Но в какой-то момент происходит интересная вещь: когда перечитываешь не факты, а свои эмоции годовалой давности - внутри что-то щелкает
Медитация, среди прочего, учит нас замечать непостоянную природу наших мыслей.
Дневники показывают нам непостоянную природу наших более длительных состояний.
В следующий раз немного расскажу о формате своих ежедневных записей и об отслеживание целей с помощью дневника
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡3🤔1🤯1🥴1
❗️ Конец Blue-Green: мы выбрали процесс вместо костыля
В прошлой части остановился на вопросе: «строим систему надёжнее или умный костыль, который однажды станет нашей главной точкой отказа?»
Сегодня - ответ. И он не тот, который я планировал
➡️ Куда мы пришли технически
К моменту ревью всё почти работало:
DevOps выкатили Blue-Green в продакшен: два окружения, единый ingress, переключение трафика по кнопке
Со стороны Django: пропатченная команда makemigrations, разделение операций на конструктивные и деструктивные, тулинг для двухфазных миграций
На горизонте - переход на дневные релизы. Цель, ради которой всё затевалось
Оставалось пройти код-ревью и описать процесс работы с новой схемой
🛑 Тех.лид пришёл с альтернативой
На ревью пришёл наш тех.лид - назовём его Серёга. И принёс ссылку на статью про паттерн Expand & Contract. По его мнению - вот правильный способ решать совместимость схемы БД. А моя реализация ему «не нравится»
Я уперся рогами. Двухфазные миграции работали, корнер-кейсы отрабатывали - я готов был защищать решение до последнего
🔍 Архитектурный комитет как место для дебатов
На архком мы приходили не раз и не два
Серёга стоял на том, что задача решается процессом. Я - на том, что процесс нужно подкрепить технологией, чтобы переход был безболезненным
Каждый раунд уходили в детали, прорабатывали корнер-кейсы, возвращались с новыми аргументами. Серёга не мог доказать, что моё решение не работает. Я не мог честно объяснить, зачем оно нужно поверх процесса
В фоне всё это время висел один вопрос: «зачем»
💡 Кто потребитель схемы БД
Озарение пришло на одном из таких ADR. Простой вопрос: на кого вообще рассчитан этот механизм совместимости?
Я строил систему, которая поддерживает консистентность для двух потребителей - Blue и Green. То есть для двух версий бэкенда
Но у схемы БД потребителей сильно больше: смежные сервисы, отчёты, аналитика, фоновые задачи, внешние интеграции. Технология даёт контракт ровно для двух клиентов. Для всех - нужны бесконечные деньги и ресурсы, которыми мы, к сожалению, не обладаем
А корректно работающий процесс - покрывает 100% случаев. Не в вакууме, а в реальной жизни. Это не так элегантно, как техническое решение в идеальных условиях. Но несоизмеримо эффективнее
✅ Финал
Я сдался. Признал капитуляцию, отпустил рога и пошёл внедрять процесс
Цель осталась той же - Zero Downtime и дневные релизы. Изменились только средства. Через неделю после последнего архкома мы выкатили первый релиз в дневное время. Без костыля, только на процессе
Эта история длиной в 3.5 года потом легла в основу моего доклада на Moscow Python №107. Финальный тезис серии и доклада совпадает:
А Серёга оказался единственным голосом разума на всю компанию. Я слишком долго не верил, что проблему нельзя решить технически. В итоге пришёл к тому, что можно - но не полностью
В прошлой части остановился на вопросе: «строим систему надёжнее или умный костыль, который однажды станет нашей главной точкой отказа?»
Сегодня - ответ. И он не тот, который я планировал
➡️ Куда мы пришли технически
К моменту ревью всё почти работало:
DevOps выкатили Blue-Green в продакшен: два окружения, единый ingress, переключение трафика по кнопке
activate {color}Со стороны Django: пропатченная команда makemigrations, разделение операций на конструктивные и деструктивные, тулинг для двухфазных миграций
На горизонте - переход на дневные релизы. Цель, ради которой всё затевалось
Оставалось пройти код-ревью и описать процесс работы с новой схемой
🛑 Тех.лид пришёл с альтернативой
На ревью пришёл наш тех.лид - назовём его Серёга. И принёс ссылку на статью про паттерн Expand & Contract. По его мнению - вот правильный способ решать совместимость схемы БД. А моя реализация ему «не нравится»
Я уперся рогами. Двухфазные миграции работали, корнер-кейсы отрабатывали - я готов был защищать решение до последнего
🔍 Архитектурный комитет как место для дебатов
На архком мы приходили не раз и не два
Серёга стоял на том, что задача решается процессом. Я - на том, что процесс нужно подкрепить технологией, чтобы переход был безболезненным
Каждый раунд уходили в детали, прорабатывали корнер-кейсы, возвращались с новыми аргументами. Серёга не мог доказать, что моё решение не работает. Я не мог честно объяснить, зачем оно нужно поверх процесса
В фоне всё это время висел один вопрос: «зачем»
💡 Кто потребитель схемы БД
Озарение пришло на одном из таких ADR. Простой вопрос: на кого вообще рассчитан этот механизм совместимости?
Я строил систему, которая поддерживает консистентность для двух потребителей - Blue и Green. То есть для двух версий бэкенда
Но у схемы БД потребителей сильно больше: смежные сервисы, отчёты, аналитика, фоновые задачи, внешние интеграции. Технология даёт контракт ровно для двух клиентов. Для всех - нужны бесконечные деньги и ресурсы, которыми мы, к сожалению, не обладаем
А корректно работающий процесс - покрывает 100% случаев. Не в вакууме, а в реальной жизни. Это не так элегантно, как техническое решение в идеальных условиях. Но несоизмеримо эффективнее
✅ Финал
Я сдался. Признал капитуляцию, отпустил рога и пошёл внедрять процесс
Цель осталась той же - Zero Downtime и дневные релизы. Изменились только средства. Через неделю после последнего архкома мы выкатили первый релиз в дневное время. Без костыля, только на процессе
Эта история длиной в 3.5 года потом легла в основу моего доклада на Moscow Python №107. Финальный тезис серии и доклада совпадает:
Не пишите костыли, процессы рулят
А Серёга оказался единственным голосом разума на всю компанию. Я слишком долго не верил, что проблему нельзя решить технически. В итоге пришёл к тому, что можно - но не полностью
Prisma's Data Guide
Using the expand and contract pattern | Prisma's Data Guide
In this article, we introduce the expand and contract pattern to help migrate data and clients to a new schema.
👍2😁1🤯1
👋 Вчера был на встрече с программным комитетом Saint HighLoad!
Записался туда, по большей части, из любопытства
Пока что выступления на конференциях такого уровня кажутся мне чем-то сверх
Хотелось взглянуть на их кухню, пообщаться с людьми и в целом полезно провести вечер
Возможно, унести с собой какие-то инсайты
🔍 Ничего неожиданного не произошло - и это, пожалуй, главное наблюдение
Я увидел людей, которые уже выступали раньше, выступают сейчас и будут выступать дальше
Пообщался с организаторами, с опытными и начинающими спикерами, СТО и СЕО местных компаний, юристами из бигтехов
И все-таки кое-что я понял:
🍺 Про формат встречи
Мероприятие проходило в полуподвальном барном помещении
Видимо, чтобы забустить нетворкинг легким градусом пенного. И у них получилось!
В начале организаторы рассказывали об основной цели встречи - донести обновленный формат и манифест конференции 2026 года
Основная идея простая:
- учить значит вовлекать!
🧠 Про формат обучения
Дальше много раз подчеркивалось, что приоритет будут отдавать интерактивным форматам
Воркшопам, обсуждениям, экспериментам с залом
Последний спикер показал это на практике
Один приветственный слайд и вопрос в зал:
Дальше были споры, примеры и живые реакции
Ровно тот формат обучения, о котором все и говорили
⚖️ Про напряжения и ограничения
Название HighLoad по-прежнему многими считывается как история только для бигтеха
Хотя в зале было много людей из маленьких команд с сильным и интересным опытом
Отдельный холивар вызвала тема HR бренда
Всем интересно слушать не только про успехи
А про внутреннюю кухню, ошибки и рост
Но именно эти темы чаще всего не проходят корпоративные фильтры BigTech
🔁 Про более широкий сдвиг
Если вынести это за рамки одной конференции, становится заметен более общий сдвиг
Информация сегодня перестала быть ценностью сама по себе
Базовые знания можно получить за вечер
Но понимание без опыта не держится
Люди на сцене - те же люди вокруг, которые на себя еще одну роль - спикера, тренера или организатора.
✔️ В конце у меня удалось пропитчить несколько своих идей и получить ценную обратную связь от зала и от организаторов. Буду пробовать подавать! Кто знает, что из этого выйдет?
#MINDSET #NOTES
Записался туда, по большей части, из любопытства
Пока что выступления на конференциях такого уровня кажутся мне чем-то сверх
Хотелось взглянуть на их кухню, пообщаться с людьми и в целом полезно провести вечер
Возможно, унести с собой какие-то инсайты
🔍 Ничего неожиданного не произошло - и это, пожалуй, главное наблюдение
Я увидел людей, которые уже выступали раньше, выступают сейчас и будут выступать дальше
Пообщался с организаторами, с опытными и начинающими спикерами, СТО и СЕО местных компаний, юристами из бигтехов
И все-таки кое-что я понял:
Доклады на больших конференциях - это не редкая врожденная особенность членов закрытого клуба
Это просто дополнительная работа обычных работяг, которые видят выступления и обмен знаниями частью своего карьерного трека
🍺 Про формат встречи
Мероприятие проходило в полуподвальном барном помещении
Видимо, чтобы забустить нетворкинг легким градусом пенного. И у них получилось!
В начале организаторы рассказывали об основной цели встречи - донести обновленный формат и манифест конференции 2026 года
Основная идея простая:
- учить значит вовлекать!
🧠 Про формат обучения
Дальше много раз подчеркивалось, что приоритет будут отдавать интерактивным форматам
Воркшопам, обсуждениям, экспериментам с залом
Последний спикер показал это на практике
Один приветственный слайд и вопрос в зал:
Что должно быть на конференции, чтобы на нее прийти?
И что - чтобы прийти, заплатив из своего кармана?
Дальше были споры, примеры и живые реакции
Ровно тот формат обучения, о котором все и говорили
⚖️ Про напряжения и ограничения
Название HighLoad по-прежнему многими считывается как история только для бигтеха
Хотя в зале было много людей из маленьких команд с сильным и интересным опытом
Отдельный холивар вызвала тема HR бренда
Всем интересно слушать не только про успехи
А про внутреннюю кухню, ошибки и рост
Но именно эти темы чаще всего не проходят корпоративные фильтры BigTech
🔁 Про более широкий сдвиг
Если вынести это за рамки одной конференции, становится заметен более общий сдвиг
Информация сегодня перестала быть ценностью сама по себе
Базовые знания можно получить за вечер
Но понимание без опыта не держится
Чтобы действительно чему-то научить, нужно вовлекатьДля меня самым важным оказалось ощущение нормальности происходящего
Давать возможность думать, спорить и ошибаться
Создавать опыт, а не просто передавать информацию
И именно это я увидел на встрече
В формате и поведении людей
Люди на сцене - те же люди вокруг, которые на себя еще одну роль - спикера, тренера или организатора.
✔️ В конце у меня удалось пропитчить несколько своих идей и получить ценную обратную связь от зала и от организаторов. Буду пробовать подавать! Кто знает, что из этого выйдет?
#MINDSET #NOTES
⚡7🔥4❤2😁1🥴1