За двенадцать лет в архитектуре я видел три классических способа разобраться с монолитом, который перестал помещаться в голову: переписать с нуля, заморозить и поддерживать минимально, и постепенно…
За двенадцать лет я приходил в проекты, где «вся архитектура — в голове у Васи, который уволился полгода назад». Каждый раз одно и то же: команда боится трогать ключевые куски, потому что не…
Сценарий, который я разбирал не раз: consumer получает событие OrderCreated, обработчик падает с NullPointerException, retry-механизм брокера повторяет доставку. Раз, два, тысячу раз. Consumer-под…
Distributed tracing решает задачу красиво, но не везде применим: легаси-сервисы без OTel-агента, кроссплатформенные интеграции, where the trace context не пробрасывается. Часто проще иметь хотя бы…
Запрос пришёл от пользователя в API gateway, оттуда — в orders, оттуда — в payments и inventory параллельно, payments позвал внешний эквайер, ответ собрался обратно. Где-то в этой цепочке произошёл…
CQRS (Command Query Responsibility Segregation) — паттерн, про который чаще говорят, чем по-настоящему применяют. Идея простая: команды (изменяющие операции) и запросы (читающие) — это разные модели,…
Когда первый раз поднимаешь Kafka и пишешь в неё JSON, всё кажется простым. Продьюсер кладёт байты, консьюмер читает байты, согласование держится на устной договорённости. Через шесть месяцев у вас…
Exactly-once delivery — самый продаваемый и самый недопонятый термин в распределёнке. На презентациях производителей брокеров он звучит как магия. На проде через полгода работы инженеры обнаруживают,…
«Health check» в инженерной практике обычно сводят к разговору про probes в оркестраторе. Это операционная сторона, и она важна, но в ней часто теряется главное: health check — это контракт сервиса.…
Когда отдельно взятый сервис умеет завершаться корректно, это половина дела. Вторая половина начинается, когда таких сервисов десять, между ними сетевые вызовы и общие очереди, и кто-то нажал…
Outbox pattern в учебниках всегда показывают на Kafka. Это создаёт ложное впечатление, что без Kafka паттерн «не настоящий». На самом деле outbox решает универсальную проблему — атомарность записи в…
Текстовый лог в файле — это удобно, пока сервисов не больше двух. Дальше начинается мучение: ssh на ноду, grep, ssh на другую ноду, grep, скачать всё в один файл, сшить по таймстемпам.…
Event sourcing звучит красиво в любой презентации: «храним не состояние, а историю изменений», «полный аудит из коробки», «можно восстановить любой момент». Я знаю три проекта, которые на этом…
Связка «изменили данные в БД и опубликовали событие в брокер» — самая частая точка отказа в распределённых системах. Я разбирал её в трёх компаниях, и каждый раз корень был один: команда пыталась…
«У каждого сервиса своя база» — одно из тех правил, которые звучат настолько разумно, что хочется применить везде сразу. На бумаге всё аккуратно: сервисы независимы, релизятся отдельно, схему меняет…
Любой код, который ходит в сеть, рано или поздно встречается с сетевой ошибкой. Сервис прислал 503, БД таймаутнула, gRPC отвалился по дедлайну. Логичный рефлекс — повторить запрос. Логичный, но…
«Сделаем микросервис» — фраза, которую я слышал в трёх разных компаниях, и в двух из них через год команда жалела. Микросервис, выделенный без причины, добавляет сетевые хопы, новые БД, отдельные…
Eventual consistency — это не «лучшая или худшая» согласованность, это просто другая модель. Сильные гарантии, к которым все привыкли в одной базе, в распределённой системе либо стоят дорого, либо…
Когда смотришь, как зрелая команда разрезает большую систему, разговор почти всегда сводится не к таблицам и не к сервисам, а к тому, какими словами разные группы людей называют одно и то же. У…
Микросервисы интегрируются через API. Тесты у каждой команды свои. Каждая ходит в моки соседей. На стейдже всё зелено. На проде ловите 500 от orders, потому что payments выкатил релиз, в котором поле…
Backend for Frontend появился как ответ на конкретную боль: разные клиенты (веб, iOS, Android, умный холодильник) дёргают одни и те же бекенд-сервисы, но каждому нужен свой формат данных, свой набор…
Outbox pattern закрывает половину задачи: producer гарантирует, что событие будет опубликовано хотя бы раз. Но «хотя бы раз» означает «возможно, дважды». На стороне consumer'а это превращается в…
«Сервис должен быть надёжным» — фраза, под которой все согласно кивают, но никто не понимает одинаково. Для разработчика «надёжный» = «не падает при моём релизе». Для product owner — «работает, когда…
Сценарий, который я разбирал не раз: сервис заказов зовёт сервис каталога. Каталог тормозит, ответы идут по 5 секунд вместо 50 миллисекунд. Пул потоков сервиса заказов забивается ожиданием каталога,…
Гексагональная архитектура (она же ports & adapters) — одна из тех концепций, про которые проще всего написать что-то вроде «отделите бизнес-логику от инфраструктуры» и закончить статью. Проблема в…
Распределённая транзакция в микросервисах — миф, который по инерции живёт в голове у людей, перешедших из мира монолита. Двухфазный коммит между четырьмя сервисами на разных БД технически возможен,…
«Нам нужен gateway» и «мы переезжаем на service mesh» — две фразы, которые я слышу на проектах с микросервисами с одинаковой регулярностью. И каждый раз приходится разбираться, что именно команда…
Когда новый сервис должен жить в одной экосистеме со старой системой, у разработчика обычно два варианта. Первый — взять формат данных и понятия легаси как есть, протащить их сквозь свой код и через…
Сценарий, который я разбирал в трёх разных компаниях: сервис принимает заказ, пишет его в Postgres и шлёт событие OrderCreated в Kafka. Логика понятная, код в одном методе, тесты зелёные. На проде…
Rate limiting — это не «защита от DDoS», как часто думают. DDoS лечится на уровне инфраструктуры (CDN, anti-DDoS-прокси). Rate limiting в API-сервисе решает другие задачи: справедливое распределение…
Когда новый разработчик впервые слышит «у нас API версии v1», он представляет себе аккуратный мир: есть версия, она зафиксирована, под нее написаны клиенты, через год выйдет v2, все мирно мигрируют.…
Сценарий, который я разбирал в трёх компаниях: сервис A зовёт сервис B и сервис C. B начинает тормозить, отвечает по 5 секунд. Запросы к B забивают весь пул потоков сервиса A. Запросы к C, которые…
POST на /payments вернул 504. Клиент не знает, прошёл платёж или нет, и нажимает кнопку ещё раз. Через минуту в базе два списания на одного пользователя. Классика, которую я разбирал в трёх компаниях…
Сценарий, который повторяется на каждом проекте с микросервисами на старте: команда делает первые два сервиса, прописывает hardcoded URL http://orders-service:8080 в конфиге payments. Работает. Через…
«Микросервисы» в современных командах часто превращаются в религиозный термин. На стартапе из пяти человек поднимают пятнадцать сервисов с своими репозиториями, своими CI и своими очередями, потому…