Почему я перестал гоняться за «идеальной» архитектурой и начал проектировать под хаос

Misha_Backend
2026-08-03 14:24
Все мы прошли через фазу, когда хотелось выстроить систему как по учебнику: чистая гексагональная архитектура, event-driven, CQRS, саги, outbox — и чтобы всё это работало как часы. Я тоже так хотел. Пока не попал на проект, где требования меняются быстрее, чем я успеваю переименовать миграции, а «бизнес-логика» в голове заказчика — это просто «сделай, чтобы работало, а детали потом». Смотрите, в чём проблема. Мы, бэкендеры, любим строить красивые абстракции. Разбиваем монолит на микросервисы, вводим доменные события, оборачиваем всё в репозитории. Но через полгода выясняется, что 80% сервисов — это просто CRUD с одним эндпоинтом, а вся «сложность» — в инфраструктуре: Kafka, Redis, оркестратор. И вот ты сидишь и думаешь: зачем я здесь городил сагу, если можно было просто вызвать REST из другого сервиса и не париться с компенсациями? Я не говорю, что архитектура не нужна. Я говорю, что нужно проектировать под хаос — то есть под реальные условия эксплуатации. Возьмём пример: у вас есть сервис заказов и сервис оплаты. По учебнику — асинхронная коммуникация через брокер, outbox-паттерн, обработка дублей. По факту — вам нужно, чтобы заказ создался и оплата прошла в течение секунды, иначе юзер уйдёт. Если вы воткнёте между ними Kafka, вы добавите задержку и кучу точек отказа. Проще сделать синхронный вызов с retry и идемпотентностью. Да, это «не идеально», но это работает и легко дебажится. Второй момент — это переиспользование. Я как-то видел проект, где для каждой сущности создавали отдельный микросервис. В итоге было 40 сервисов, из которых 35 — это одинаковые CRUD с разными полями. Поддерживать это — ад: каждый сервис со своим деплоем, логами, метриками. Я бы сделал один generic-сервис с конфигурацией, но нет — «архитектурные принципы» не позволяли. Так вот, принципы должны быть гибкими. Если у вас двадцать раз повторяется одно и то же — это не «микросервисы», это плохой дизайн. Теперь про базы данных. Вечная тема: PostgreSQL всем хорош, но вот NoSQL модно. Я видел, как люди переносили на MongoDB то, что отлично жило в реляционке, а потом мучились с агрегациями и транзакциями. Мой подход: если данные связаны и нужны отчёты — это SQL. Если это лог событий или кэш — Redis или что-то подобное. Не надо лепить графовые базы для дружбы юзеров, если хватит таблицы friends с индексами. Простота — это тоже архитектура. Ещё один пункт — тестирование. Я перестал писать юнит-тесты на каждый чих. Серьёзно. Если у меня есть интеграционные тесты, которые гоняют реальный сценарий через БД и брокер, они ловят больше багов, чем сотни моков. Моки — это иллюзия безопасности: они тестируют ваши ожидания, а не реальность. Поэтому я теперь сначала пишу e2e-сценарий, а потом уже покрываю критичные куски юнитами. Это экономит кучу времени и нервов. И последнее — про мониторинг. Любая, даже самая уродливая архитектура, становится терпимой, если у тебя есть хорошие логи и трейсинг. Я в каждом сервисе прокидываю request ID, собираю метрики в Prometheus и строю дашборды. Когда что-то падает, я не гадаю — я вижу, где именно. Это спасло меня от десятков ночных инцидентов. Без этого ваша идеальная архитектура — просто груда кода, которая рано или поздно взорвётся. Так что мой совет: не бойтесь выглядеть «недостаточно архитектурно». Бойтесь того, что система не переживёт контакт с реальностью. Проектируйте под хаос, упрощайте, где можно, и всегда помните: код пишется для людей, а не для абстрактных паттернов. Если кто-то скажет, что ваш сервис «не по канону» — предложите ему поддержать это в проде. Кстати, кто как решает проблему «синхронный вызов vs брокер» на практике? Может, у кого-то есть конкретные критерии, кроме «так принято»? Был бы благодарен за аргументы.
👍 2
Сергей_Нуб
2026-08-03 15:36
Ох, как я тебя понимаю! 😅 Сам недавно залил на гитхаб свой «идеальный» микросервис на FastAPI с кучей абстракций, а потом понял, что для моего пет-проекта хватило бы одного файла с роутами и SQLite. Но это опыт, да. По синхронке vs брокер: у меня простое правило — если операция критична для ответа пользователю и логика не требует сложной оркестрации, я беру REST с retry и идемпотентностью. Kafka подключаю только когда нужно раздать одно событие в 5-6 потребителей или пережить пиковые нагрузки. А вообще, читал, что многие стартапы живут на синхронке до тех пор, пока это не начинает реально больно бить по задержкам. Так что твой подход с «проектированием под хаос» — это не слабость, а прагматизм. Главное, чтобы логи были — а то без них даже самый простой CRUD превращается в квест по поиску бага 🕵️♂️
Сергей_Нуб
2026-08-03 16:08
Слушай, я прям подпишусь под каждым словом! 😄 У меня как раз была история: наклепал себе «архитектурный» пет-проект с кучей слоёв и абстракций, а потом понял, что для моего бложика хватило бы одного FastAPI с SQLite и пары роутов. Зато теперь в резюме могу написать, что «проектирую под хаос» — звучит даже круче, чем «следую DDD» 😂 По синхронке vs брокер — я для себя вывел простое правило: если операция критична для ответа пользователю и не требует сложной оркестрации — REST с retry и идемпотентностью. Kafka беру только когда реально нужно раздать событие в несколько потребителей или пережить пиковые нагрузки. А то видел проекты, где для двух сервисов городили брокер, и потом весь дебаг превращался в квест «а куда это событие улетело». Так что твой подход — это не слабость, а чистый прагматизм. Главное, чтобы логи были нормальные, а то даже самый простой CRUD без request ID — это жесть. Согласен на все 100%!
Dmitry_Optimizer
2026-08-03 18:46
Хаос — это не отсутствие порядка, а порядок, который мы пока не смоделировали. Я за десять лет в финтехе перевидал столько «идеальных» гексагональных архитектур, что они разваливались ровно в тот момент, когда в прод приходил первый легаси-костыль от бизнеса. Проблема не в хаосе, а в том, что большинство проектирует под выдуманный идеальный мир, где требования не меняются раз в неделю, а зависимости не тянут за собой зоопарк транзитивных версий. Сейчас я проектирую под хаос как под распределённую систему: явные границы, изоляция отказов, деградация вместо падения. Если сервис не переживает потерю половины своих зависимостей и не возвращает вменяемый ответ с задержкой в 500мс — значит, архитектура была не идеальной, а хрупкой. И да, Rust тут помогает: компилятор не даст вам наступить на грабли с гонками, но он не спасёт от идиотских бизнес-правил, которые меняются по ходу релиза. Так что мой совет: проектируйте под то, что всё сломается, и тогда «идеальность» станет просто приятным бонусом, а не самоцелью.

Войдите или зарегистрируйтесь, чтобы ответить.