<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel>
<title>vikulin-va.ru</title>
<link>https://vikulin-va.ru/</link>
<description>Use Case Pattern — методология проектирования Java-сервисов: архитектура, спецификация, кейс маркетплейса и AI-агенты.</description>
<language>ru</language>
<atom:link href="https://vikulin-va.ru/rss.xml" rel="self" type="application/rss+xml"/>
<lastBuildDate>Wed, 10 Jun 2026 21:45:49 GMT</lastBuildDate>
<item>
<title>Почему jOOQ вместо JPA / MyBatis / Spring Data</title>
<link>https://vikulin-va.ru/libraries/jooq/</link>
<description>Почему мы выбрали jOOQ как persistence-слой в Use Case Pattern + DDD + CQRS. Сравнение с Hibernate/JPA, MyBatis, Spring Data JDBC: где они скрывают SQL и ломают агрегат, а где jOOQ оставляет контроль команде.</description>
<guid isPermaLink="true">https://vikulin-va.ru/libraries/jooq/</guid>
<pubDate>Fri, 8 May 2026 18:29:42 GMT</pubDate>
</item>
<item>
<title>ddd-building-blocks: DDD-абстракции для Java</title>
<link>https://vikulin-va.ru/libraries/ddd-building-blocks/</link>
<description>ddd-building-blocks — open-source библиотека DDD-абстракций для Java/Spring: Entity, AggregateRoot, ValueObject, DomainEvent, Repository, Specification. Эталонная база, на которую опираются правила R-ENT/R-AGG/R-VO и AI-скилл ucp-ddd-tactical-review.</description>
<guid isPermaLink="true">https://vikulin-va.ru/libraries/ddd-building-blocks/</guid>
<pubDate>Sat, 9 May 2026 05:36:53 GMT</pubDate>
</item>
<item>
<title>usecase-pattern — Java-библиотека UseCase / Handler / Dispatcher</title>
<link>https://vikulin-va.ru/libraries/usecase-pattern/</link>
<description>usecase-pattern — open-source Java-библиотека: UseCase / UseCaseHandler / UseCaseDispatcher, маркеры UseCaseCommand / UseCaseQuery для CQRS, Spring Boot auto-configuration, метрики Micrometer на каждый use case. Эталонная база для слоистой архитектуры Use Case Pattern.</description>
<guid isPermaLink="true">https://vikulin-va.ru/libraries/usecase-pattern/</guid>
<pubDate>Sun, 17 May 2026 07:52:11 GMT</pubDate>
</item>
<item>
<title>hexagonal-architecture — аннотации портов/адаптеров + ArchUnit</title>
<link>https://vikulin-va.ru/libraries/hexagonal-architecture/</link>
<description>hexagonal-architecture — open-source Java-библиотека: аннотации @Port, @Adapter, @UseCase для разметки слоёв Ports &amp; Adapters + ArchUnit-правила, которые ловят нарушения границ домена и инфраструктуры на каждом PR. Теория и обоснование выбора — в разделе «Гексагональная архитектура».</description>
<guid isPermaLink="true">https://vikulin-va.ru/libraries/hexagonal-architecture/</guid>
<pubDate>Sun, 17 May 2026 07:52:11 GMT</pubDate>
</item>
<item>
<title>Executable engineering standard: AI-скилл это твой ESLint для архитектуры</title>
<link>https://vikulin-va.ru/ai-engineering/executable-standard/</link>
<description>У вас уже есть линтер для запятых. У вас нет линтера для агрегатов и доменных событий. AI-скиллы с corpus правил — это второй линтер, и его исполняет LLM. Сравнение с SonarQube и ESLint, концепт «rule corpus + executor», когда не нужен.</description>
<guid isPermaLink="true">https://vikulin-va.ru/ai-engineering/executable-standard/</guid>
<pubDate>Thu, 7 May 2026 19:28:02 GMT</pubDate>
</item>
<item>
<title>AI-скиллы vs SonarQube vs ESLint vs ревью тимлидом</title>
<link>https://vikulin-va.ru/ai-engineering/vs-sonarqube/</link>
<description>Чем AI-скиллы как executable engineering standard отличаются от SonarQube, ESLint и обычного code review глазами тимлида. Таблица сравнения по 12 параметрам, когда что использовать вместе.</description>
<guid isPermaLink="true">https://vikulin-va.ru/ai-engineering/vs-sonarqube/</guid>
<pubDate>Thu, 7 May 2026 19:28:02 GMT</pubDate>
</item>
<item>
<title>AI пишет код. Зачем тогда методология?</title>
<link>https://vikulin-va.ru/ai-engineering/methodology-and-ai/</link>
<description>Самое частое возражение к Use Case Pattern: «зачем учить методологию, если Claude и так пишет код». Полный ответ с экспериментом, пятью сценариями где AI без методологии разваливается, разбором что такое «общий контекст» технически, и историческими параллелями.</description>
<guid isPermaLink="true">https://vikulin-va.ru/ai-engineering/methodology-and-ai/</guid>
<pubDate>Thu, 7 May 2026 18:16:30 GMT</pubDate>
</item>
<item>
<title>Как ревьюить код, который написал AI</title>
<link>https://vikulin-va.ru/ai-engineering/ai-code-review/</link>
<description>Объём AI-кода в 5–10 раз выше, обычный review-цикл размыкается. Что искать в первую очередь, что отдать автоматам, как масштабировать через AI-скиллы и spec-as-code. Антипаттерны, чек-лист команды на 15 пунктов.</description>
<guid isPermaLink="true">https://vikulin-va.ru/ai-engineering/ai-code-review/</guid>
<pubDate>Thu, 7 May 2026 18:16:30 GMT</pubDate>
</item>
<item>
<title>AI как design-критик: то, что не делает code-generator</title>
<link>https://vikulin-va.ru/ai-engineering/ai-design-critique/</link>
<description>AI как код-генератор известен. Менее известно — он делает работу архитектора, которую человек обычно проваливает: валидация спеки до кодогенерации. Ловит синонимы в Ubiquitous Language, агрегаты с &gt;7 инвариантами, события без потребителей, команды без владельца. 9 категорий проверок и скилл ucp-spec-review.</description>
<guid isPermaLink="true">https://vikulin-va.ru/ai-engineering/ai-design-critique/</guid>
<pubDate>Thu, 7 May 2026 18:16:30 GMT</pubDate>
</item>
<item>
<title>Какой язык программирования выбрать для AI-кодинга в команде</title>
<link>https://vikulin-va.ru/ai-engineering/language-for-ai/</link>
<description>Для одиночного разработчика язык вторичен — AI работает везде. Для команды на годы — определяющий выбор. Четыре критерия AI-friendly языка, сравнение Java/Python/Go/Rust/Scala и других, что компенсировать если стек уже выбран.</description>
<guid isPermaLink="true">https://vikulin-va.ru/ai-engineering/language-for-ai/</guid>
<pubDate>Thu, 7 May 2026 18:16:30 GMT</pubDate>
</item>
<item>
<title>AI-native компания: маленькая команда + агенты, и почему ей всё равно нужна методология</title>
<link>https://vikulin-va.ru/ai-engineering/ai-native-company/</link>
<description>PO + тимлид + по одному senior-инженеру на компетенцию + Claude и агенты вместо штата — модель, в которой 3–7 человек выкатывают продукт, на который раньше нужны были 30–50. Что это такое, как устроена разработка внутри, где разваливается без методологии, и что нужно положить поверх, чтобы кодовая база пережила первый год.</description>
<guid isPermaLink="true">https://vikulin-va.ru/ai-engineering/ai-native-company/</guid>
<pubDate>Thu, 7 May 2026 18:16:30 GMT</pubDate>
</item>
<item>
<title>Уровень зрелости 0: As-is (реверс из кода)</title>
<link>https://vikulin-va.ru/use-case-pattern/level-0/</link>
<description>Нижняя ступень: спецификация восстановлена из существующего кода без бизнес-брифа. Снимок «как сейчас» для онбординга brownfield-сервиса и точка отсчёта для миграции на уровень 1/2/3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/use-case-pattern/level-0/</guid>
<pubDate>Fri, 22 May 2026 05:58:06 GMT</pubDate>
</item>
<item>
<title>Уровень зрелости 1: Слоёный</title>
<link>https://vikulin-va.ru/use-case-pattern/level-1/</link>
<description>Базовая ступень: слоёная архитектура Controller → Service → Repository без Use Case Pattern. Когда её достаточно, где она ломается и какой сигнал говорит, что пора на уровень 2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/use-case-pattern/level-1/</guid>
<pubDate>Sun, 26 Apr 2026 15:57:40 GMT</pubDate>
</item>
<item>
<title>Уровень зрелости 2: Use Case Pattern</title>
<link>https://vikulin-va.ru/use-case-pattern/level-2/</link>
<description>Каждая бизнес-операция — отдельный UseCase + Handler, общий диспетчер, метрики на операцию. CQRS (UseCaseCommand / UseCaseQuery + Read Model) — опция этого уровня.</description>
<guid isPermaLink="true">https://vikulin-va.ru/use-case-pattern/level-2/</guid>
<pubDate>Sun, 26 Apr 2026 15:57:40 GMT</pubDate>
</item>
<item>
<title>Уровень зрелости 3: DDD + Hexagonal</title>
<link>https://vikulin-va.ru/use-case-pattern/level-3/</link>
<description>Высший уровень: инварианты живут в доменной модели (агрегаты, value objects, доменные события), а инфраструктура изолирована портами и адаптерами с ArchUnit. DDD и Hexagonal — один уровень.</description>
<guid isPermaLink="true">https://vikulin-va.ru/use-case-pattern/level-3/</guid>
<pubDate>Sun, 26 Apr 2026 15:57:40 GMT</pubDate>
</item>
<item>
<title>Use Case спецификация: формат</title>
<link>https://vikulin-va.ru/use-case-pattern/spec-template/</link>
<description>Формат спецификации Bounded Context: один файл на контекст + по файлу на агрегат, домен без техники, карточки команд и запросов, события у агрегатов, контракты на рёбрах интеграций. Уровни зрелости 1/2/3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/use-case-pattern/spec-template/</guid>
<pubDate>Sun, 26 Apr 2026 15:33:23 GMT</pubDate>
</item>
<item>
<title>Use Case Pattern: пошаговый гид по применению</title>
<link>https://vikulin-va.ru/use-case-pattern/howto/</link>
<description>Практический гид: что и в каком порядке делать, чтобы получить результат. Два сценария — один UseCase за 3 минуты и целый сервис от спеки до прода за день-два. Команды, ожидаемый результат, чек-листы и антипаттерны.</description>
<guid isPermaLink="true">https://vikulin-va.ru/use-case-pattern/howto/</guid>
<pubDate>Wed, 29 Apr 2026 19:22:29 GMT</pubDate>
</item>
<item>
<title>Настройка Claude Code под UCP (Use Case Pattern)</title>
<link>https://vikulin-va.ru/use-case-pattern/plugins-setup/</link>
<description>Установка стека за 5 шагов: usecase-pattern-skills, superpowers (оркестратор), context7 (актуальная документация). Два сценария — один UseCase за 3 минуты и целый сервис от спеки до прода за день-два. Решение проблем.</description>
<guid isPermaLink="true">https://vikulin-va.ru/use-case-pattern/plugins-setup/</guid>
<pubDate>Tue, 28 Apr 2026 15:17:55 GMT</pubDate>
</item>
<item>
<title>Карта сервисов маркетплейса: от бизнес-брифа к архитектуре</title>
<link>https://vikulin-va.ru/case/services-map/</link>
<description>Промежуточный артефакт между бизнес-брифом и спекой Уровня 3 каждого сервиса. На примере маркетплейса показано 7 шагов: Event Storming → Bounded Contexts → монолит vs микросервисы → карта сервисов с границами → data ownership → интеграции (sync/async/Saga) → failure domains → C4. Без этого пласта AI быстро сгенерирует код по плохой спеке.</description>
<guid isPermaLink="true">https://vikulin-va.ru/case/services-map/</guid>
<pubDate>Mon, 4 May 2026 17:44:28 GMT</pubDate>
</item>
<item>
<title>Notification Service — Use Case спецификация (Уровень 1)</title>
<link>https://vikulin-va.ru/case/notification-service/</link>
<description>Полная Use Case спецификация Notification Service из кейса маркетплейса. Уровень 1: классическая слоёная архитектура без UseCase Pattern и DDD. Контрпример к Order Service — показывает, когда DDD избыточен.</description>
<guid isPermaLink="true">https://vikulin-va.ru/case/notification-service/</guid>
<pubDate>Mon, 27 Apr 2026 07:08:32 GMT</pubDate>
</item>
<item>
<title>Catalog Service — Use Case спецификация (Уровень 2)</title>
<link>https://vikulin-va.ru/case/catalog-service/</link>
<description>Полная Use Case спецификация Catalog Service из кейса маркетплейса. Уровень 2: UseCase Pattern без DDD-агрегатов. Простая state machine, ABAC-проверки в handler'е, jOOQ-репозитории.</description>
<guid isPermaLink="true">https://vikulin-va.ru/case/catalog-service/</guid>
<pubDate>Mon, 27 Apr 2026 18:58:07 GMT</pubDate>
</item>
<item>
<title>Catalog Service: пошаговая генерация от бизнес-описания до кода</title>
<link>https://vikulin-va.ru/case/catalog-service-walkthrough/</link>
<description>Полный сеанс работы с Use Case Pattern на примере Catalog Service: конкретные промпты, выдержки из ответов AI, последовательность команд от бизнес-описания до работающего кода. Уровень 2 за 3 часа.</description>
<guid isPermaLink="true">https://vikulin-va.ru/case/catalog-service-walkthrough/</guid>
<pubDate>Wed, 29 Apr 2026 19:35:11 GMT</pubDate>
</item>
<item>
<title>Order Service — Use Case спецификация (Уровень 3)</title>
<link>https://vikulin-va.ru/case/order-service/</link>
<description>Use Case спецификация Order Service из кейса маркетплейса. Уровень 3 (DDD + Hexagonal): три агрегата — Order, Dispute, Refund. Домен без техники, события у агрегатов, контракты на рёбрах, Outbox и ABAC.</description>
<guid isPermaLink="true">https://vikulin-va.ru/case/order-service/</guid>
<pubDate>Sun, 26 Apr 2026 17:43:35 GMT</pubDate>
</item>
<item>
<title>Что такое DDD и зачем он нужен</title>
<link>https://vikulin-va.ru/domain-driven-design/01-what-is-ddd/</link>
<description>Введение в Domain Driven Design: какую проблему он решает, когда оправдан и когда избыточен, основные концепции — доменная модель, контексты, единый язык. База перед стратегическими и тактическими паттернами.</description>
<guid isPermaLink="true">https://vikulin-va.ru/domain-driven-design/01-what-is-ddd/</guid>
<pubDate>Sat, 11 Apr 2026 15:41:43 GMT</pubDate>
</item>
<item>
<title>Стратегические паттерны DDD</title>
<link>https://vikulin-va.ru/domain-driven-design/02-strategic-patterns/</link>
<description>Стратегические паттерны DDD: Bounded Context, Context Map, Ubiquitous Language, поддомены (core/supporting/generic). Как разрезать большую систему на сервисы по бизнес-смыслу, а не по таблицам.</description>
<guid isPermaLink="true">https://vikulin-va.ru/domain-driven-design/02-strategic-patterns/</guid>
<pubDate>Sat, 11 Apr 2026 15:41:43 GMT</pubDate>
</item>
<item>
<title>Тактические паттерны DDD</title>
<link>https://vikulin-va.ru/domain-driven-design/03-tactical-patterns/</link>
<description>Тактические паттерны DDD: Entity, Value Object, Aggregate, Repository, Domain Event — с примерами Java/Spring и описанием каждого паттерна. Правила-якоря с кодами R-ENT/R-VO/R-AGG для AI-ревью — в DDD Tactical Style Guide.</description>
<guid isPermaLink="true">https://vikulin-va.ru/domain-driven-design/03-tactical-patterns/</guid>
<pubDate>Sat, 11 Apr 2026 15:41:43 GMT</pubDate>
</item>
<item>
<title>Интеграционные паттерны DDD</title>
<link>https://vikulin-va.ru/domain-driven-design/04-integration-patterns/</link>
<description>Интеграционные паттерны DDD: ACL (Anti-Corruption Layer), Open Host Service, Published Language, Conformist, Customer/Supplier. Как соединять Bounded Context-ы без утечки чужой модели в свой код.</description>
<guid isPermaLink="true">https://vikulin-va.ru/domain-driven-design/04-integration-patterns/</guid>
<pubDate>Sat, 11 Apr 2026 15:41:43 GMT</pubDate>
</item>
<item>
<title>Принципы проектирования в DDD</title>
<link>https://vikulin-va.ru/domain-driven-design/05-design-principles/</link>
<description>Принципы проектирования в DDD: инварианты внутри агрегата, границы транзакций по агрегату, eventual consistency между агрегатами. Базовые правила, которые ловятся AI-скиллом ucp-ddd-tactical-review на ревью PR.</description>
<guid isPermaLink="true">https://vikulin-va.ru/domain-driven-design/05-design-principles/</guid>
<pubDate>Sat, 11 Apr 2026 15:41:43 GMT</pubDate>
</item>
<item>
<title>CQRS</title>
<link>https://vikulin-va.ru/patterns/cqrs/</link>
<description>CQRS: разделение моделей чтения и записи. Когда применять, цена eventual consistency, как ложится на Use Case Pattern уровня 2 и Spring Boot. Без переусложнения.</description>
<guid isPermaLink="true">https://vikulin-va.ru/patterns/cqrs/</guid>
<pubDate>Mon, 18 May 2026 07:54:55 GMT</pubDate>
</item>
<item>
<title>Гексагональная архитектура</title>
<link>https://vikulin-va.ru/patterns/hexagonal/</link>
<description>Ports &amp; Adapters: изоляция бизнес-логики от инфраструктуры. Gradle multi-module, домен на чистой Java, тесты без Spring. Соответствует Use Case Pattern уровня 4 — берётся под сложные модули, не везде.</description>
<guid isPermaLink="true">https://vikulin-va.ru/patterns/hexagonal/</guid>
<pubDate>Mon, 18 May 2026 07:54:55 GMT</pubDate>
</item>
<item>
<title>Паттерны авторизации</title>
<link>https://vikulin-va.ru/patterns/auth-patterns/</link>
<description>Обучающий гайд по аутентификации и авторизации для SPA, мобильных приложений и микросервисов: OAuth2, JWT, RBAC, ABAC. Со схемами и Spring Boot примерами. Стандартные правила с кодами AUTH-N — отдельным style guide.</description>
<guid isPermaLink="true">https://vikulin-va.ru/patterns/auth-patterns/</guid>
<pubDate>Mon, 18 May 2026 07:54:55 GMT</pubDate>
</item>
<item>
<title>Распределённые паттерны</title>
<link>https://vikulin-va.ru/patterns/distributed-patterns/</link>
<description>2PC, 3PC, SAGA, Transactional Outbox, CDC, Event Sourcing, Idempotent Consumer, Distributed Lock — как обеспечить согласованность данных между сервисами. Когда какой паттерн оправдан, как ложится на Java/Spring и Kafka.</description>
<guid isPermaLink="true">https://vikulin-va.ru/patterns/distributed-patterns/</guid>
<pubDate>Mon, 18 May 2026 07:54:55 GMT</pubDate>
</item>
<item>
<title>Паттерны отказоустойчивости</title>
<link>https://vikulin-va.ru/patterns/resilience/</link>
<description>Retry, Circuit Breaker, Timeout, Bulkhead, Fallback, Rate Limiter, DLQ на Java/Resilience4j. Как ограничить радиус поражения при сбоях соседних сервисов и не уронить свой при нагрузке.</description>
<guid isPermaLink="true">https://vikulin-va.ru/patterns/resilience/</guid>
<pubDate>Mon, 18 May 2026 07:54:55 GMT</pubDate>
</item>
<item>
<title>Структурные паттерны микросервисов</title>
<link>https://vikulin-va.ru/patterns/microservices-structural/</link>
<description>API Gateway, BFF, Sidecar, Service Mesh, Strangler Fig, ACL, Service Discovery — как организовать взаимодействие сервисов. Примеры на Spring Cloud Gateway.</description>
<guid isPermaLink="true">https://vikulin-va.ru/patterns/microservices-structural/</guid>
<pubDate>Mon, 18 May 2026 07:54:55 GMT</pubDate>
</item>
<item>
<title>Батч-процессинг: от @Scheduled-цикла к очереди задач</title>
<link>https://vikulin-va.ru/patterns/batch-processing/</link>
<description>Разбор фоновой обработки на реальном коде: чем ломается наивный @Scheduled-полер и как его чинят — FOR UPDATE SKIP LOCKED, lease, ретраи с backoff, Spring Batch, брокер.</description>
<guid isPermaLink="true">https://vikulin-va.ru/patterns/batch-processing/</guid>
<pubDate>Sat, 6 Jun 2026 17:10:31 GMT</pubDate>
</item>
<item>
<title>Протокол AMQP: exchange, queue, binding, ack</title>
<link>https://vikulin-va.ru/amqp/protocol/</link>
<description>Модель AMQP 0.9.1: четыре типа exchange (direct, topic, fanout, headers), routing keys, bindings, queues, ack/nack/reject, prefetch (basic.qos), publisher confirms, mandatory/immediate, TTL и max-length. Без привязки к конкретному брокеру.</description>
<guid isPermaLink="true">https://vikulin-va.ru/amqp/protocol/</guid>
<pubDate>Mon, 18 May 2026 08:24:13 GMT</pubDate>
</item>
<item>
<title>RabbitMQ в production: Quorum Queues, кластеризация, мониторинг</title>
<link>https://vikulin-va.ru/amqp/rabbitmq-production/</link>
<description>Как RabbitMQ работает в проде: кластеризация (все-узлы-знают-всё), три типа queue (Classic / Quorum / Streams), отказ от classic mirroring в 4.0, persistence и lazy queue, federation/shovel для гео-репликации, мониторинг через Prometheus + Management UI, sizing и backpressure.</description>
<guid isPermaLink="true">https://vikulin-va.ru/amqp/rabbitmq-production/</guid>
<pubDate>Mon, 18 May 2026 08:24:13 GMT</pubDate>
</item>
<item>
<title>Spring AMQP: RabbitTemplate, @RabbitListener, retry, DLX</title>
<link>https://vikulin-va.ru/amqp/spring-amqp/</link>
<description>Практический гайд по spring-amqp / spring-rabbit: RabbitTemplate для публикации, @RabbitListener + ConcurrentRabbitListenerContainerFactory, MessageConverter (Jackson), обработка ошибок и retry, декларативный Dead Letter Exchange, publisher confirms, transactional listener. С примерами Java-кода.</description>
<guid isPermaLink="true">https://vikulin-va.ru/amqp/spring-amqp/</guid>
<pubDate>Mon, 18 May 2026 08:24:13 GMT</pubDate>
</item>
<item>
<title>Messaging-паттерны через AMQP: work queue, pub/sub, RPC, idempotency</title>
<link>https://vikulin-va.ru/amqp/patterns/</link>
<description>Шесть классических messaging-паттернов на AMQP/RabbitMQ: work queue (распределение нагрузки), publish/subscribe (broadcast), routing (тематическая маршрутизация), topic (иерархия событий), RPC (запрос-ответ через reply-to + correlation-id), idempotent consumer. Плюс delayed retry, Dead Letter pattern, Outbox через AMQP.</description>
<guid isPermaLink="true">https://vikulin-va.ru/amqp/patterns/</guid>
<pubDate>Mon, 18 May 2026 08:24:13 GMT</pubDate>
</item>
<item>
<title>AMQP vs Kafka: какой брокер брать</title>
<link>https://vikulin-va.ru/amqp/vs-kafka/</link>
<description>Сравнение двух моделей: AMQP (queue, push, message-consumed-once) и Kafka (log, pull, replay). Семь конкретных критериев выбора: характер потока, ordering, throughput, retention, ack model, routing flexibility, операционная сложность. Сценарии где AMQP, где Kafka, и когда обе вместе.</description>
<guid isPermaLink="true">https://vikulin-va.ru/amqp/vs-kafka/</guid>
<pubDate>Mon, 18 May 2026 08:24:13 GMT</pubDate>
</item>
<item>
<title>Apache Kafka: топики, партиции, порядок и гарантии</title>
<link>https://vikulin-va.ru/kafka/fundamentals/</link>
<description>Что внутри Kafka: топики, партиции, ключи, consumer groups, гарантии доставки (at-most/at-least/exactly-once), idempotent producer, transactional producer + outbox, replication, retention. Без привязки к конкретному фреймворку.</description>
<guid isPermaLink="true">https://vikulin-va.ru/kafka/fundamentals/</guid>
<pubDate>Mon, 18 May 2026 08:04:20 GMT</pubDate>
</item>
<item>
<title>Kafka в production: Spring Kafka, DLQ, Schema Registry, тюнинг, KRaft</title>
<link>https://vikulin-va.ru/kafka/production-essentials/</link>
<description>Что Java/Spring-разработчику нужно знать про Kafka сверх основ: Spring Kafka (@KafkaListener, KafkaTemplate, ErrorHandler, @RetryableTopic), Dead Letter Queue, Schema Registry с Avro/Protobuf и режимы совместимости, headers и трейсинг, consumer lag и его причины, performance tuning (batch.size / linger.ms / compression), безопасность (SASL/SSL/ACL), KRaft вместо ZooKeeper.</description>
<guid isPermaLink="true">https://vikulin-va.ru/kafka/production-essentials/</guid>
<pubDate>Mon, 18 May 2026 08:04:20 GMT</pubDate>
</item>
<item>
<title>Kubernetes Fundamentals: pod, deployment, service</title>
<link>https://vikulin-va.ru/kubernetes/fundamentals/</link>
<description>Kubernetes для backend-разработчика: зачем pod поверх контейнера, как Deployment держит желаемое состояние, зачем Service над смертными подами и как запрос доходит до приложения.</description>
<guid isPermaLink="true">https://vikulin-va.ru/kubernetes/fundamentals/</guid>
<pubDate>Sat, 6 Jun 2026 18:14:04 GMT</pubDate>
</item>
<item>
<title>Сеть в Kubernetes: Service, DNS, Ingress, NetworkPolicy</title>
<link>https://vikulin-va.ru/kubernetes/networking/</link>
<description>Как сервисы находят друг друга в Kubernetes: типы Service, DNS-имена, путь через Ingress и Gateway API, связь readiness и endpoints, NetworkPolicy и место service mesh.</description>
<guid isPermaLink="true">https://vikulin-va.ru/kubernetes/networking/</guid>
<pubDate>Sat, 6 Jun 2026 18:14:04 GMT</pubDate>
</item>
<item>
<title>Spring Boot в Kubernetes: probes, ресурсы и JVM, graceful shutdown</title>
<link>https://vikulin-va.ru/kubernetes/spring-boot-in-k8s/</link>
<description>Зона ответственности разработчика в Kubernetes: probes через Actuator, requests/limits и память JVM (OOMKilled), graceful shutdown без потери запросов, ConfigMap, HPA.</description>
<guid isPermaLink="true">https://vikulin-va.ru/kubernetes/spring-boot-in-k8s/</guid>
<pubDate>Sat, 6 Jun 2026 18:14:04 GMT</pubDate>
</item>
<item>
<title>Деплой в Kubernetes: манифесты, Helm, rolling update, GitOps</title>
<link>https://vikulin-va.ru/kubernetes/deploy-and-config/</link>
<description>Как сервис доезжает до кластера: манифесты vs kustomize vs Helm, механика rolling update и связь с readiness, откаты, GitOps, миграции БД при безостановочном деплое.</description>
<guid isPermaLink="true">https://vikulin-va.ru/kubernetes/deploy-and-config/</guid>
<pubDate>Sat, 6 Jun 2026 18:14:04 GMT</pubDate>
</item>
<item>
<title>Kubernetes на практике: kubectl-набор и разбор типичных инцидентов</title>
<link>https://vikulin-va.ru/kubernetes/operations/</link>
<description>Отладка сервиса в Kubernetes: рабочий kubectl-набор и разбор инцидентов — CrashLoopBackOff, OOMKilled, ImagePullBackOff, Pending, мигающая readiness, «запрос не доходит».</description>
<guid isPermaLink="true">https://vikulin-va.ru/kubernetes/operations/</guid>
<pubDate>Sat, 6 Jun 2026 18:14:04 GMT</pubDate>
</item>
<item>
<title>AWS Fundamentals: аккаунты, IAM, регионы, VPC</title>
<link>https://vikulin-va.ru/aws/fundamentals/</link>
<description>Модель AWS для backend-разработчика: организация аккаунтов, IAM (роли вместо ключей), регионы и зоны доступности, VPC без сетевой магии — подсети, security groups.</description>
<guid isPermaLink="true">https://vikulin-va.ru/aws/fundamentals/</guid>
<pubDate>Sat, 6 Jun 2026 18:24:35 GMT</pubDate>
</item>
<item>
<title>Вычисления в AWS: EC2, ECS, EKS или Lambda для Spring-сервиса</title>
<link>https://vikulin-va.ru/aws/compute/</link>
<description>Где запускать backend в AWS: EC2 как ручной режим, ECS/Fargate как контейнеры без кластера, EKS как managed Kubernetes, Lambda и её границы для JVM. Критерии и ошибки.</description>
<guid isPermaLink="true">https://vikulin-va.ru/aws/compute/</guid>
<pubDate>Sat, 6 Jun 2026 18:24:35 GMT</pubDate>
</item>
<item>
<title>Managed-данные в AWS: RDS, ElastiCache, SQS, MSK</title>
<link>https://vikulin-va.ru/aws/managed-data/</link>
<description>Managed-данные AWS против self-hosted: RDS/Aurora для PostgreSQL, ElastiCache, SQS против RabbitMQ, MSK против своей Kafka, ниша DynamoDB. Что облако снимает, что оставляет.</description>
<guid isPermaLink="true">https://vikulin-va.ru/aws/managed-data/</guid>
<pubDate>Sat, 6 Jun 2026 18:24:35 GMT</pubDate>
</item>
<item>
<title>AWS из Spring: SDK v2, credentials chain, Spring Cloud AWS, LocalStack</title>
<link>https://vikulin-va.ru/aws/spring-integration/</link>
<description>Работа с AWS из Spring Boot: SDK v2 и клиенты-бины, credentials chain без ключей в коде, Spring Cloud AWS для SQS и секретов, LocalStack в тестах, цена вызовов.</description>
<guid isPermaLink="true">https://vikulin-va.ru/aws/spring-integration/</guid>
<pubDate>Sat, 6 Jun 2026 18:24:35 GMT</pubDate>
</item>
<item>
<title>Безопасность и наблюдаемость в AWS: Secrets Manager, KMS, CloudWatch</title>
<link>https://vikulin-va.ru/aws/security-observability/</link>
<description>Секреты и шифрование в AWS: Secrets Manager с ротацией, KMS, CloudTrail как аудит. Наблюдаемость: CloudWatch против связки Prometheus/Grafana — когда что.</description>
<guid isPermaLink="true">https://vikulin-va.ru/aws/security-observability/</guid>
<pubDate>Sat, 6 Jun 2026 18:24:35 GMT</pubDate>
</item>
<item>
<title>Принципы CI/CD: конвейер от коммита до прода</title>
<link>https://vikulin-va.ru/cicd/pipeline-principles/</link>
<description>Что делает конвейер доставки надёжным: артефакт собирается один раз, быстрые проверки раньше медленных, pipeline as code, зелёный main, деплой отделён от релиза.</description>
<guid isPermaLink="true">https://vikulin-va.ru/cicd/pipeline-principles/</guid>
<pubDate>Sat, 6 Jun 2026 18:36:12 GMT</pubDate>
</item>
<item>
<title>CI для Java/Spring: сборка, тесты, quality gates</title>
<link>https://vikulin-va.ru/cicd/ci-java/</link>
<description>Конвейер CI для Spring-сервиса: Gradle-сборка с кешами, слои тестов (unit → Testcontainers), quality gates — SAST, зависимости, секреты. Что блокирует merge, а что нет.</description>
<guid isPermaLink="true">https://vikulin-va.ru/cicd/ci-java/</guid>
<pubDate>Sat, 6 Jun 2026 18:36:12 GMT</pubDate>
</item>
<item>
<title>Стратегии релиза: rolling, blue-green, canary, feature flags</title>
<link>https://vikulin-va.ru/cicd/release-strategies/</link>
<description>Как выкатывать без страха: rolling update, blue-green с мгновенным откатом, canary с метриками-критериями, feature flags как разделение деплоя и релиза. Выбор стратегии.</description>
<guid isPermaLink="true">https://vikulin-va.ru/cicd/release-strategies/</guid>
<pubDate>Sat, 6 Jun 2026 18:36:12 GMT</pubDate>
</item>
<item>
<title>Ветки и релизный цикл: trunk-based, версии, GitOps</title>
<link>https://vikulin-va.ru/cicd/branching-and-releases/</link>
<description>Workflow, который кормит конвейер: trunk-based против долгих веток, дисциплина коротких PR, флаги для незавершённого, версионирование, GitOps как замыкание петли.</description>
<guid isPermaLink="true">https://vikulin-va.ru/cicd/branching-and-releases/</guid>
<pubDate>Sat, 6 Jun 2026 18:36:12 GMT</pubDate>
</item>
<item>
<title>Числа и точность — bigint для id, numeric для денег</title>
<link>https://vikulin-va.ru/standards/backend/pg/numbers/</link>
<description>Числовые типы PostgreSQL: для id таблицы — bigint, без вариантов (миграция int→bigint на бою болезненная). smallint только для нумератора фиксированной шкалы. С PG 10+ — GENERATED ALWAYS AS IDENTITY, не serial/bigserial. Деньги — numeric(p,s), никогда real/double (float хранит в двоичном, 0.1+0.2≠0.3). Тип money PostgreSQL не используем (привязан к локали). real/double только для неточности (метрики, ML). Boolean — это boolean. Раскрытие PG-T-010..PG-T-016.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/numbers/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Строковые типы — text по умолчанию, никогда varchar(255)</title>
<link>https://vikulin-va.ru/standards/backend/pg/strings/</link>
<description>Строковые типы PostgreSQL: text, varchar(n), char(n) хранятся одинаково, разница только в семантике ограничения длины. По умолчанию — text; varchar(255) — наследие из MySQL/Oracle. Длину ставим когда это доменное правило (E.164, ISO 3166-1), не «техническое ограничение». char(n) почти никогда — паддинг пробелами создаёт сюрпризы. Case-insensitive: citext или functional unique index на lower(email). Кластер UTF8. TOAST автоматически выносит длинные значения (&gt;2KB). Раскрытие PG-T-020..PG-T-025.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/strings/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Время и таймзоны — timestamptz всегда, никогда timestamp</title>
<link>https://vikulin-va.ru/standards/backend/pg/time/</link>
<description>Время — самый частый источник тихих багов в проде. Для бизнес-времени всегда timestamptz, никогда timestamp без TZ. timestamptz не хранит зону — хранит UTC, конвертирует на границе I/O. На Java-стороне Instant или OffsetDateTime; LocalDateTime никогда (потеряется зона). timestamp без TZ допустим только для локального времени без привязки (расписание магазина). now() = время транзакции, clock_timestamp() = момент вызова. DateTimeService для тестируемости. INTERVAL для смещений в SQL. +infinity для бессрочных. Раскрытие PG-T-030..PG-T-035.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/time/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>UUID и идентификаторы — тип uuid, UUID v7, bigint vs UUID</title>
<link>https://vikulin-va.ru/standards/backend/pg/uuid/</link>
<description>UUID хранится в типе uuid (16 байт), никогда varchar(36)/char(36)/text (36+ байт, посимвольное сравнение, без валидации). v4 vs v7: UUID v7 (48-bit timestamp + 74 случайных бита) для PK/FK — соседние по времени id близки в btree, страницы заполняются на 90%+ vs 30-60% у v4. Генерируем на стороне приложения (UuidCreator.getTimeOrderedEpoch()) — id известен до commit. bigint IDENTITY дешевле, UUID — когда нужен (multi-service, public API, до commit). Обычная практика: bigint для внутренних FK + uuid для public_id. При UUID-PK обязательно индекс по FK. Раскрытие PG-T-040..PG-T-044.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/uuid/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Enum, boolean и перечисления — три способа выбора</title>
<link>https://vikulin-va.ru/standards/backend/pg/enum/</link>
<description>Boolean — это boolean, не smallint 0/1, не varchar Y/N. 3 способа перечисления: PG ENUM (4 байта, type-safety, но удаление значения нативно невозможно), reference table (20 байт + JOIN, full CRUD + атрибуты), text + CHECK IN (простой, без FK, до 5-7 значений). Правила выбора: редко меняется без атрибутов → ENUM; растёт, нужны атрибуты → reference table; до 5-7 без атрибутов → CHECK IN. Статусы доменных сущностей обычно reference table. ENUM миграционные ловушки: ADD VALUE мгновенно но в отдельной tx, удаление нативно невозможно. Java enum, не String. Не путать: status vs lifecycle (переходы это state machine). Раскрытие PG-T-050..PG-T-052.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/enum/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>JSONB — когда оправдан, когда нет</title>
<link>https://vikulin-va.ru/standards/backend/pg/jsonb/</link>
<description>JSONB — мощный тип, который часто используют не по назначению. Всегда jsonb, не json. Главное правило: если по полю регулярно фильтруют, сортируют, джойнят — это колонка, не JSON-ключ. Хорошие случаи: журнал аудита (payload полиморфен по event_type), полиморфные атрибуты товара, интеграционные конфиги, кеш-копии external API. Плохо: все поля сущности в одном data jsonb, поле по которому ищут регулярно, JSONB чтобы не писать миграции. Базовые операторы -&gt; -&gt;&gt; #&gt; #&gt;&gt; @&gt; ?. GIN с jsonb_path_ops для @&gt;; functional index дешевле для конкретного ключа. Не пишите бинарь, большие тексты, base64. Раскрытие PG-T-060..PG-T-067.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/jsonb/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Массивы и range-типы — теги, бронирования, EXCLUDE constraint</title>
<link>https://vikulin-va.ru/standards/backend/pg/arrays-ranges/</link>
<description>PostgreSQL умеет хранить массивы и интервалы (range-типы). Массив уместен: набор скалярных значений, до десятков, нет отдельной идентичности, не нужно ссылаться извне. Массив неуместен: атрибуты у элементов (это таблица), ссылки на элементы, тысячи элементов. GIN-индекс для @&gt;, &amp;&amp;, ANY. Range-типы (tstzrange, daterange) — когда сущность сама по себе интервал (тариф, бронь, цена с историей). Атомарная семантика, @&gt; и &amp;&amp; операторы вместо длинных WHERE. EXCLUDE constraint — уникальная возможность PG для гарантии непересечения через btree_gist. По умолчанию [) — корректное &amp;&amp; без перекрытия концов. Multirange (PG14+) для расписаний. Раскрытие PG-T-070..PG-T-074.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/arrays-ranges/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Именование объектов в PostgreSQL — snake_case, единственное число, префиксы</title>
<link>https://vikulin-va.ru/standards/backend/pg/naming/</link>
<description>Именование PostgreSQL: snake_case для всего, никаких кавычек в идентификаторах. Таблицы — существительные в единственном числе (order_doc, customer); junction-таблицы — обе сущности в порядке. Колонки: id, FK — &lt;parent&gt;_id, boolean — is_/has_/can_, время — _at для timestamp, деньги — _amount/_price/_rate, длительность — _seconds/_ms. Audit: created_at, updated_at, version; soft-delete — deleted_at, не is_deleted. Индексы префикс по типу: ix_/uk_/ck_/fk_. Зарезервированные слова (user, order) не использовать. Лимит 63, целевая до 30 символов. Раскрытие PG-N-001..PG-N-094.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/naming/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Типы индексов в PostgreSQL — B-tree, GIN, GiST, BRIN</title>
<link>https://vikulin-va.ru/standards/backend/pg/indexes-types/</link>
<description>PostgreSQL поддерживает шесть типов индексов: B-tree (дефолт 80-90%), Hash (почти никогда), GIN (JSONB, массивы, full-text), GiST (range, PostGIS, EXCLUDE), BRIN (огромные append-only), SP-GiST (IP-префиксы). pg_trgm для LIKE %X%. Partial index с WHERE — размер в разы меньше. Раскрытие PG-I-020..PG-I-026.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/indexes-types/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Composite-индексы и левый префикс — порядок колонок</title>
<link>https://vikulin-va.ru/standards/backend/pg/indexes-composite/</link>
<description>Composite-индексы: индекс работает только на левый префикс полей (a,b,c) — WHERE a, WHERE a AND b, WHERE a AND b AND c; для WHERE b или c — Seq Scan. Порядок в WHERE не важен — оптимизатор переставляет. Первым = равенство, range последним. ORDER BY совпадает с индексом. Дубликаты не нужны. INCLUDE — покрывающий без раздувания ключа. FK обязательно с индексом. Раскрытие PG-I-010..PG-I-018.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/indexes-composite/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Как выбрать индекс и считать селективность</title>
<link>https://vikulin-va.ru/standards/backend/pg/indexes-selectivity/</link>
<description>Селективность колонки = distinct/total. Индекс на низкоселективной (is_deleted, status) бесполезен. &lt; 5-10% через = обычно индекс; &gt; 20% обычно seq-scan. random_page_cost 1.1 на SSD (default 4.0 под HDD). Композитный может работать там где single-column бесполезен. ANALYZE после массовой загрузки. CREATE STATISTICS для коррелирующих колонок. Раскрытие PG-I-030..PG-I-037.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/indexes-selectivity/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>EXPLAIN ANALYZE — типы узлов и как читать план</title>
<link>https://vikulin-va.ru/standards/backend/pg/explain/</link>
<description>EXPLAIN (ANALYZE, BUFFERS) — стандарт. Реальное время узла = actual time × loops. Расхождение rows/actual rows 10x+ = ANALYZE. Filter vs Index Cond — если важное условие в Filter, индекс не используется. Heap Fetches &gt; 0 на Index Only Scan — VACUUM. Batches &gt; 1 в Hash Join — work_mem. external merge Disk в Sort — work_mem или индекс. Раскрытие PG-E-030..PG-E-039.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/explain/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Блокировки и как использовать их с jOOQ</title>
<link>https://vikulin-va.ru/standards/backend/pg/locks/</link>
<description>PostgreSQL три уровня блокировок: table (DDL), row (SELECT FOR UPDATE), advisory. UPDATE/DELETE автоматически берут row-level. SELECT FOR UPDATE — read-modify-write защита, только в @Transactional. SKIP LOCKED — distributed очередь задач. Pessimistic vs Optimistic (version-колонка для read-heavy). Advisory lock для глобальных операций. Deadlock — упорядочивание по PK. @Retryable на CannotAcquireLockException. Раскрытие PG-L-001..PG-L-095.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/locks/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Уровни изоляции и аномалии</title>
<link>https://vikulin-va.ru/standards/backend/pg/isolation-levels/</link>
<description>PG 3 уровня: READ COMMITTED (default), REPEATABLE READ (snapshot), SERIALIZABLE (SSI). PG RC строже стандарта — dirty read невозможен. PG RR — snapshot, phantom предотвращён. Только SERIALIZABLE ловит write skew. Дефолт RC в 95% случаев. 40001 на RR/SERIALIZABLE требует @Retryable. idle_in_transaction_session_timeout 30s. Раскрытие PG-IS-001..PG-IS-082.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/isolation-levels/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Spring @Transactional — нюансы и антипаттерны</title>
<link>https://vikulin-va.ru/standards/backend/pg/transactional-spring/</link>
<description>Spring @Transactional: на UseCase/Handler, не на репозитории, не на контроллере. Self-invocation не работает — выноси в отдельный бин. Метод public. REQUIRED (default), REQUIRES_NEW (отдельная TX + соединение). readOnly=true: setReadOnly + skip flush + routing на replica. rollbackFor: только RuntimeException; checked не откатывают. @TransactionalEventListener AFTER_COMMIT. TX секунды, не минуты. Раскрытие PG-TX-001..PG-TX-097.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/transactional-spring/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>HikariCP и connection pooling — формула Wooldridge, PgBouncer</title>
<link>https://vikulin-va.ru/standards/backend/pg/connection-pool/</link>
<description>Формула Wooldridge: 2N+1 = 10-20 для SSD. «Больше = больше throughput» миф. HikariCP: max=min-idle (нет ramp-up), connection-timeout 3s, max-lifetime 30 мин, leak-detection 60s. PgBouncer для много инстансов/serverless — transaction mode оптимален но prepareThreshold 0, SET LOCAL, нет LISTEN/NOTIFY. Read-replica отдельный пул + routing через readOnly. Раскрытие PG-CP-001..PG-CP-086.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/connection-pool/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Миграции и breaking changes без даунтайма</title>
<link>https://vikulin-va.ru/standards/backend/pg/migrations/</link>
<description>ALTER TABLE берёт ACCESS EXCLUSIVE. N-1 правило. Expand-Contract на 3+ релиза. SET LOCAL lock_timeout 3s. SET NOT NULL через CHECK NOT VALID + VALIDATE + SET NOT NULL. ADD FK через NOT VALID + VALIDATE. CREATE INDEX CONCURRENTLY, runInTransaction=false. Удаление enum нативно невозможно — теневой тип. UPDATE миллионов — backfill-job, не миграция. Rollback почти не работает — forward-fix. squawk линтер. Раскрытие PG-M-001..PG-M-140.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/migrations/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Полнотекстовый поиск (FTS) — tsvector, GIN, russian</title>
<link>https://vikulin-va.ru/standards/backend/pg/fts/</link>
<description>PG FTS закрывает 90% задач поиска без Elasticsearch. Хватает ≤ 10M документов, ≤ 100 RPS. Generated column tsvector ... STORED + GIN-индекс. russian для стемминга. websearch_to_tsquery (PG11+) Google-style. ts_headline для подсветки. setweight A/B/C/D. pg_trgm дополняет для fuzzy и коротких полей. Раскрытие PG-FTS-001..PG-FTS-094.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/fts/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Materialized views и стратегии refresh</title>
<link>https://vikulin-va.ru/standards/backend/pg/materialized-views/</link>
<description>MV = закэшированный snapshot тяжёлого запроса. Подходит для агрегаций, отчётов, dashboards, pre-computed search. UNIQUE-индекс обязателен для CONCURRENTLY refresh. REFRESH MATERIALIZED VIEW CONCURRENTLY — стандарт. Инкрементальный через pg_ivm. @Scheduled 5 минут для отчётов. Debouncing через Redis-флаг лучше триггера AFTER. Раскрытие PG-MV-001..PG-MV-041.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/materialized-views/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Партиционирование — когда, как, по какому ключу</title>
<link>https://vikulin-va.ru/standards/backend/pg/partitioning/</link>
<description>Партиционируй если &gt; 50 GB / 100M строк, time-series, удаление по сроку, autovacuum не справляется. Избыточно &lt; 10 GB. 3 типа: RANGE (самый частый), LIST, HASH (редко). Ключ должен быть в WHERE почти всех запросов. Размер партиции 1-50 GB; &gt; 1000 — тормоза. DROP TABLE партиции мгновенный vs DELETE минуты. PK обязан включать ключ. pg_partman для автоматизации. Раскрытие PG-P-001..PG-P-085.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/partitioning/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Multi-tenancy паттерны — row, schema, db per tenant</title>
<link>https://vikulin-va.ru/standards/backend/pg/multi-tenancy/</link>
<description>3 паттерна: row-per-tenant (default до тысяч тенантов), schema-per-tenant (enterprise с регуляторными), db-per-tenant (≤ десятков). Row-per-tenant: tenant_id первой колонкой везде; каждый запрос WHERE tenant_id; RLS для defense in depth. SET LOCAL app.tenant_id обязателен. Schema-per-tenant не масштабируется до тысяч (pg_class распухает). Гибрид — самое частое. Раскрытие PG-MT-001..PG-MT-085.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/multi-tenancy/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>PostGIS для геоданных — точки, полигоны, поиск в радиусе</title>
<link>https://vikulin-va.ru/standards/backend/pg/postgis/</link>
<description>PostGIS закрывает 95% задач для геоданных без отдельной БД. geography(Point, 4326) — default. POINT(lon lat) — долгота сначала. GiST-индекс обязателен. ST_DWithin использует индекс, ST_Distance без WHERE — нет. &lt;-&gt; для kNN. ST_Contains/ST_Within/ST_Intersects для полигонов. JTS на Java. Generated column geography из lat/lon. Раскрытие PG-GIS-001..PG-GIS-095.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/postgis/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Репликация для разработчика — read-replica и routing</title>
<link>https://vikulin-va.ru/standards/backend/pg/replication/</link>
<description>Streaming replication: master пишет WAL → реплика проигрывает. Replication lag 50-500ms норма. Routing через AbstractRoutingDataSource + LazyConnectionDataSourceProxy (обязателен — без него Spring выбирает DataSource до знания readOnly). Read-after-write антипаттерн — read-from-master, возврат из write, или wait for catch-up. Synchronous replication обычно не нужно. Failover через HikariCP + @Retryable. Алёрт replay_lag &gt; 30 сек. Раскрытие PG-RP-001..PG-RP-085.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/replication/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Расширения, которые часто нужны — pgcrypto, pg_trgm, btree_gist</title>
<link>https://vikulin-va.ru/standards/backend/pg/extensions/</link>
<description>На любой проект: pg_stat_statements (мониторинг, требует shared_preload_libraries), pgcrypto (gen_random_uuid, crypt bcrypt), pg_trgm (LIKE %X% + опечатки). btree_gist для EXCLUDE и composite GiST. citext — case-insensitive text. pg_partman для автоматизации партиций. pg_repack для реорганизации без блокировки. hstore legacy → jsonb. uuid-ossp устарел → gen_random_uuid. Раскрытие PG-EXT-001..PG-EXT-153.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/extensions/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Триггеры и хранимые процедуры — когда НЕ надо</title>
<link>https://vikulin-va.ru/standards/backend/pg/triggers/</link>
<description>Бизнес-логика в коде, не в БД. Триггер для updated_at — антипаттерн, лучше DEFAULT now() + явный UPDATE. Денормализация триггером терпимо, но MV/event-handler гибче. Audit-trail триггером оправдан для compliance (банки, медицина). CHECK &gt; триггер для простых инвариантов. Stored procedures почти никогда — @Transactional покрывает. FOR EACH ROW дорог на bulk. Триггеры могут вызывать deadlock. Раскрытие PG-TR-001..PG-TR-095.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/triggers/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>VACUUM, autovacuum и bloat</title>
<link>https://vikulin-va.ru/standards/backend/pg/vacuum/</link>
<description>MVCC: UPDATE/DELETE копят dead tuples. VACUUM освобождает место в FSM (не возвращает на диск), обновляет visibility map, предотвращает XID wraparound. VACUUM не блокирует чтение/запись. VACUUM FULL почти никогда в проде (ACCESS EXCLUSIVE). autovacuum scale_factor 0.05 на больших горячих. Bloat обнаружение через n_dead_tup и pgstattuple. fillfactor 80-90 на write-heavy. Долгие TX блокируют освобождение. Раскрытие PG-V-001..PG-V-080.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/vacuum/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Мониторинг и slow queries</title>
<link>https://vikulin-va.ru/standards/backend/pg/monitoring/</link>
<description>pg_stat_statements — топ запросов. auto_explain — автоматический EXPLAIN на медленных, overhead 5-20%. log_min_duration_statement 500ms-1s. pg_stat_activity для текущих, алёрт xact_age &gt; 5 минут. pg_stat_user_tables: n_dead_tup, last_autovacuum, idx_scan=0. Cache hit ratio &gt; 95%. Цикл диагностики «медленно»: activity → statements → IO → bloat → replication → OS. Раскрытие PG-MON-001..PG-MON-094.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/monitoring/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Backup и restore — что должен знать разработчик</title>
<link>https://vikulin-va.ru/standards/backend/pg/backup/</link>
<description>Два класса: логический (pg_dump SQL-дамп, гранулярность) и физический (pg_basebackup, весь кластер, PITR). pg_dump -Fc + pg_restore -j 4 parallel. Прод физический + WAL archive для PITR (recovery_target_time). Retention: daily 7d + weekly 4w + monthly 12m. Backup всегда в отдельном хранилище. Тестировать restore. При катастрофе: STOP → DBA → current state → PITR. Раскрытие PG-BK-001..PG-BK-084.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/backup/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>WAL и как разработчик влияет на него</title>
<link>https://vikulin-va.ru/standards/backend/pg/wal/</link>
<description>WAL = журнал всех изменений. fsync WAL в каждом COMMIT — цена durability. UPDATE пишет новую строку целиком, не дельту (кроме HOT). COPY вместо INSERT — 10-100x. HOT и fillfactor 80-90 на write-heavy. TOAST не переписывается если не изменился. UNLOGGED таблицы для сессий/кешей (нулевой WAL). synchronous_commit=off для аналитики. Долгие TX блокируют освобождение. Раскрытие PG-W-001..PG-W-081.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/wal/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Дамп прода для разработчика — анонимизация</title>
<link>https://vikulin-va.ru/standards/backend/pg/anonymization/</link>
<description>Никогда не передавай прод-дамп без анонимизации (GDPR / 152-ФЗ). Default — синтетический dataset через faker. PII: имя, email, телефон, адрес, паспорт, ИНН, дата рождения, IP, карта. Стратегии: удаление, замена константой, псевдонимизация (md5), faker, shuffle, generalization. Email — псевдонимизация через md5. postgresql_anonymizer для декларативных правил. Re-identification через комбинацию полей. Раскрытие PG-AN-001..PG-AN-072.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/anonymization/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Антипаттерны типов — сводный чек-лист</title>
<link>https://vikulin-va.ru/standards/backend/pg/antipatterns/</link>
<description>Сводный список антипаттернов схем: varchar(255), timestamp без TZ, varchar(36) для UUID, float для денег, serial/bigserial, smallint/char(1) вместо boolean, PG ENUM для растущего списка, JSONB как гибкая схема, массив вместо таблицы, valid_from/valid_to вместо range, тип money, LocalDateTime для timestamptz, Instant.now() напрямую, UUID v4 для PK. Чек-лист на ревью схемы, индексов, миграции. Раскрытие PG-T-080..PG-T-093.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/pg/antipatterns/</guid>
<pubDate>Sat, 9 May 2026 04:42:30 GMT</pubDate>
</item>
<item>
<title>Именование — пакеты, классы, методы, переменные, константы</title>
<link>https://vikulin-va.ru/standards/backend/java/style/naming/</link>
<description>Именование в Java: пакеты в нижнем регистре без подчёркиваний, единственное число (java.util, не java.utils). Классы — существительные; интерфейсы — существительные или -able без префикса I. Аббревиатуры: 2 буквы CAPS (IOStream), 3+ только первая большая (XmlParser). Методы — глаголы (getName, expand). Имена тестов — длинное говорящее или короткое + @DisplayName, snake_case запрещён. Переменные — camelCase. Константы — UPPER_SNAKE_CASE, обязательно static final. Раскрытие JS-2.1..JS-2.8.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/style/naming/</guid>
<pubDate>Tue, 26 May 2026 10:48:08 GMT</pubDate>
</item>
<item>
<title>Импорты — не wildcard и без unused</title>
<link>https://vikulin-va.ru/standards/backend/java/style/imports/</link>
<description>Импорты в Java: не использовать wildcard-импорты (import some.package.*) — скрывает откуда что приходит, ломает сборку при коллизии имён. Исключение — java.util.* допустим. Не оставлять неиспользуемых импортов — IDE auto-cleanup при save должен быть включён, Checkstyle UnusedImports блокирует merge. Раскрытие JS-3.1..JS-3.2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/style/imports/</guid>
<pubDate>Tue, 26 May 2026 10:48:08 GMT</pubDate>
</item>
<item>
<title>Выражения — guard, method references и порядок модификаторов</title>
<link>https://vikulin-va.ru/standards/backend/java/style/expressions/</link>
<description>Выражения в Java: сложность булева выражения не более 3 операторов &amp;&amp;/||. Java-стиль массивов (int[] nums, не int nums[]). Порядок модификаторов: public/protected/private → static → final → transient → volatile → synchronized. Не указывать неявные модификаторы (public/abstract в methods интерфейса; static во вложенных enum). Method reference вместо лямбды где имеет смысл. Большие лямбды (&gt; 1 выражения) выносить в named methods. Guard expression вместо вложенных условий — early return после условия-нарушения. Раскрытие JS-4.1..JS-4.7.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/style/expressions/</guid>
<pubDate>Tue, 26 May 2026 10:48:08 GMT</pubDate>
</item>
<item>
<title>Отступы и форматирование — 120 символов и без выравнивания</title>
<link>https://vikulin-va.ru/standards/backend/java/style/formatting/</link>
<description>Отступы и форматирование Java: длина строки не более 120 символов включая отступы. Перенос длинных выражений: после запятой для аргументов; перед оператором для арифметики; сопоставление новой строки с началом выражения. Не использовать горизонтальное выравнивание переменных — diff-noise при переименовании. .editorconfig обеспечивает консистентность между IDE/редакторами. Раскрытие JS-5.1..JS-5.3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/style/formatting/</guid>
<pubDate>Tue, 26 May 2026 10:48:08 GMT</pubDate>
</item>
<item>
<title>Lombok — @RequiredArgsConstructor, @Slf4j и запрет @Data</title>
<link>https://vikulin-va.ru/standards/backend/java/style/lombok/</link>
<description>Lombok в UCP: @RequiredArgsConstructor всегда для классов с private final-полями. @Slf4j вместо ручного LoggerFactory.getLogger. @Getter на custom exceptions с payload и value-objects не record. Lombok НЕ на records (record уже даёт ctor/accessors/equals/hashCode/toString). @Data ЗАПРЕЩЁН в production — mutable setters + equals/hashCode по всем полям. @Builder точечно (5+ полей в DTO; запрещён на aggregate root — построение через named-конструкторы). @Getter/@Setter для mutable классов где record неприменим (jOOQ POJO, JPA entity). Запреты: явный all-args ctor где подошёл @RequiredArgsConstructor; @AllArgsConstructor на DI-классах. Раскрытие JS-6.1..JS-6.8 и JS-6.X1..JS-6.X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/style/lombok/</guid>
<pubDate>Tue, 26 May 2026 10:48:08 GMT</pubDate>
</item>
<item>
<title>Комментарии — без Javadoc и без кодов правил в исходниках</title>
<link>https://vikulin-va.ru/standards/backend/java/style/comments/</link>
<description>Комментарии в UCP: по умолчанию не пишем — хорошее имя класса/метода/переменной + структура уже отвечают на «что делает». Комментарий уместен только когда WHY неочевиден. Не цитируем коды правил из спеки и стайл-гайдов в коде (BR-C5, AUTH-15, R-LAY-3 не попадают в исходники). Не пишем «что тут было», «убрано для X», «TODO до spring 4» — git blame. Javadoc не используем нигде, включая публичный API библиотек — гниёт быстрее кода. Запреты: /** ... */ блок с тегами @param, @return, @throws, @see; конфигурация javadoc-task в build.gradle. Раскрытие JS-7.1..JS-7.5 и JS-7.X1..JS-7.X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/style/comments/</guid>
<pubDate>Tue, 26 May 2026 10:48:08 GMT</pubDate>
</item>
<item>
<title>Современные фичи Java — sealed, switch expressions, records</title>
<link>https://vikulin-va.ru/standards/backend/java/style/modern-java/</link>
<description>Современные фичи Java 21+: switch expression на sealed-иерархии вместо if-else цепочек — компилятор гарантирует exhaustiveness. Record patterns в case для деконструкции. Record patterns в instanceof. Exhaustive switch без default для sealed-иерархий — default превращает compile-time error в runtime. Sealed interfaces для closed-набора альтернатив (None/Reused/Created). String.formatted() вместо String.format() — читается линейно. Records для in-class data carriers (3-5 полей, только в этом классе) — private record без Lombok. Раскрытие JS-8.1..JS-8.7.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/style/modern-java/</guid>
<pubDate>Tue, 26 May 2026 10:48:08 GMT</pubDate>
</item>
<item>
<title>Enforcement через Checkstyle — механические правила</title>
<link>https://vikulin-va.ru/standards/backend/java/style/checkstyle/</link>
<description>Enforcement Java Style Guide через Checkstyle: подключается через стандартный checkstyle gradle plugin с конфигом config/checkstyle/checkstyle.xml в репо. Покрывает механические правила: именование, импорты, отступы, whitespace. Семантические правила (Lombok-defaults, комментарии, Java 21+ фичи) в Checkstyle не выносим — false positive утопят сигнал; применяются скиллом ucp-java-style-review. maxWarnings=0 + ignoreFailures=false обязательно; suppression с justify и сроком до YYYY-MM-DD. Checkstyle привязан к check, не к checkSecurity. Запреты: @SuppressWarnings без justify ≥ 30 символов; удаление правил локально; Checkstyle для семантики. Раскрытие JS-CS-1..JS-CS-5 и JS-CS-X1..JS-CS-X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/style/checkstyle/</guid>
<pubDate>Tue, 26 May 2026 10:48:08 GMT</pubDate>
</item>
<item>
<title>ACID и уровни изоляции транзакций в PostgreSQL</title>
<link>https://vikulin-va.ru/postgres/acid-and-isolation/</link>
<description>Что такое ACID, как четыре буквы реализуются в PostgreSQL (MVCC, WAL, snapshots, SSI). Четыре уровня изоляции — Read Uncommitted, Read Committed, Repeatable Read, Serializable — детально, с конкретными примерами на таблицах category и product. Когда какой уровень брать, что такое dirty read, non-repeatable read, phantom, write skew.</description>
<guid isPermaLink="true">https://vikulin-va.ru/postgres/acid-and-isolation/</guid>
<pubDate>Mon, 18 May 2026 06:27:24 GMT</pubDate>
</item>
<item>
<title>Размер БД, партиционирование и шардирование в PostgreSQL</title>
<link>https://vikulin-va.ru/postgres/partitioning-and-sharding/</link>
<description>Как считать размер базы PostgreSQL (pg_database_size, pg_total_relation_size). Когда применять партиционирование, когда — шардирование. Плюсы и минусы каждого подхода. Как выбирать ключ партиционирования и ключ шардирования. Конкретные примеры на таблицах category и product.</description>
<guid isPermaLink="true">https://vikulin-va.ru/postgres/partitioning-and-sharding/</guid>
<pubDate>Mon, 18 May 2026 06:22:20 GMT</pubDate>
</item>
<item>
<title>Covering Index в PostgreSQL: INCLUDE vs ключевая колонка</title>
<link>https://vikulin-va.ru/postgres/covering-index/</link>
<description>Что такое covering index в PostgreSQL и зачем нужен INCLUDE. Чем INCLUDE отличается от добавления колонки в ключ индекса: листовые страницы vs дерево, влияние на сортировку и уникальность, index-only scan. Когда брать INCLUDE, когда — обычный composite. Примеры на таблицах category и product.</description>
<guid isPermaLink="true">https://vikulin-va.ru/postgres/covering-index/</guid>
<pubDate>Mon, 25 May 2026 15:09:36 GMT</pubDate>
</item>
<item>
<title>Веса в полнотекстовом поиске PostgreSQL (FTS)</title>
<link>https://vikulin-va.ru/postgres/fts-weights/</link>
<description>Как правильно использовать веса A/B/C/D в полнотекстовом поиске PostgreSQL. setweight, tsvector, ts_rank, generated column + GIN-индекс. Как сделать так, чтобы совпадение в названии товара ранжировалось выше, чем в описании. Примеры на таблицах category и product.</description>
<guid isPermaLink="true">https://vikulin-va.ru/postgres/fts-weights/</guid>
<pubDate>Mon, 25 May 2026 15:09:36 GMT</pubDate>
</item>
<item>
<title>ACID, read и write concerns, транзакции в MongoDB</title>
<link>https://vikulin-va.ru/mongodb/acid-and-consistency/</link>
<description>Что MongoDB гарантирует на уровне одного документа, что — на уровне нескольких, как работают пять уровней read concern (local, available, majority, linearizable, snapshot), что значит w:majority и j:true, как использовать multi-document транзакции с 4.0, и причём тут causal consistency. Примеры на коллекциях category и product.</description>
<guid isPermaLink="true">https://vikulin-va.ru/mongodb/acid-and-consistency/</guid>
<pubDate>Mon, 18 May 2026 06:59:05 GMT</pubDate>
</item>
<item>
<title>Репликация и шардинг в MongoDB: replica set, sharded cluster, shard key</title>
<link>https://vikulin-va.ru/mongodb/replication-and-sharding/</link>
<description>Как устроена репликация в MongoDB: replica set, oplog, выбор primary, read preference. Как считать размер БД (db.stats, collection.stats). Когда переходить на sharded cluster, как устроен mongos/config server/shard, три стратегии shard key (ranged / hashed / zoned) с примерами на коллекциях category и product.</description>
<guid isPermaLink="true">https://vikulin-va.ru/mongodb/replication-and-sharding/</guid>
<pubDate>Mon, 18 May 2026 06:59:05 GMT</pubDate>
</item>
<item>
<title>Моделирование документов в MongoDB: embed vs reference, индексы</title>
<link>https://vikulin-va.ru/mongodb/schema-modeling/</link>
<description>Главный вопрос документной БД — embed или reference? Шесть правил выбора по объёму связи (one-to-few / one-to-many / one-to-millions), частоте чтения, частоте изменения. Антипаттерны с массивами без границ. Schema validation через JSON Schema. Типы индексов: single field, compound, multikey, partial, TTL.</description>
<guid isPermaLink="true">https://vikulin-va.ru/mongodb/schema-modeling/</guid>
<pubDate>Mon, 18 May 2026 06:59:05 GMT</pubDate>
</item>
<item>
<title>Spring DI/IoC, bean scopes</title>
<link>https://vikulin-va.ru/spring/di-and-lifecycle/</link>
<description>Как Spring создаёт и связывает объекты: ApplicationContext, BeanFactory, скоупы (singleton, prototype, request, session), @Configuration vs @Component, условные бины, BeanPostProcessor, циклические зависимости. Жизненный цикл бина — отдельная статья.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/di-and-lifecycle/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Жизненный цикл Spring-бина с примерами</title>
<link>https://vikulin-va.ru/spring/bean-lifecycle/</link>
<description>Восемь фаз жизненного цикла бина в Spring: instantiation, dependency injection, Aware-колбэки, BeanPostProcessor.before, инициализация (@PostConstruct/afterPropertiesSet/init-method), BeanPostProcessor.after (AOP-прокси), готовность к использованию, destruction. С рабочим демо-кодом, выводом в консоль и разбором ловушек.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/bean-lifecycle/</guid>
<pubDate>Mon, 18 May 2026 09:45:26 GMT</pubDate>
</item>
<item>
<title>Spring Boot auto-configuration, properties, profiles</title>
<link>https://vikulin-va.ru/spring/boot-auto-configuration/</link>
<description>Как Spring Boot собирает ApplicationContext автоматически: @EnableAutoConfiguration, AutoConfiguration.imports, условные бины, externalized configuration, @ConfigurationProperties vs @Value, профили, как написать собственный starter.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/boot-auto-configuration/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring MVC: REST, валидация, exception handlers</title>
<link>https://vikulin-va.ru/spring/mvc/</link>
<description>Spring MVC для REST-сервисов: DispatcherServlet и фильтры, @RestController, валидация через Bean Validation (@Valid + @Validated), единая обработка ошибок (@RestControllerAdvice), HandlerInterceptor vs OncePerRequestFilter, content negotiation, ResponseEntity vs ProblemDetail.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/mvc/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring WebFlux: когда брать, Mono/Flux, R2DBC</title>
<link>https://vikulin-va.ru/spring/webflux/</link>
<description>Reactive-стек Spring: чем отличается от Spring MVC, когда оправдан, основные типы Mono/Flux, особенности контроллеров и репозиториев (R2DBC), типичные ловушки (block, threadlocal, context propagation), границы применимости с виртуальными потоками Java 21+.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/webflux/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>@Transactional глубоко: propagation, isolation, ловушки</title>
<link>https://vikulin-va.ru/spring/transactional/</link>
<description>Как @Transactional работает под капотом через AOP-прокси, что не работает (self-invocation, private методы, checked exceptions). Все семь propagation modes с примерами, isolation, rollback rules. Distributed transactions и почему 2PC обычно нельзя.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/transactional/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring Data JPA: repositories, проекции, OSIV, fetch</title>
<link>https://vikulin-va.ru/spring/data-jpa/</link>
<description>Repository-абстракция Spring Data JPA: query methods, JPQL и Native Query, проекции (interface, class, dynamic), paging и sorting, fetch strategies, проблема OSIV (Open Session In View), N+1 и как ловить, когда переходить на jOOQ для read-side.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/data-jpa/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring Events: @EventListener, @TransactionalEventListener, AsyncEvents</title>
<link>https://vikulin-va.ru/spring/events/</link>
<description>Внутриприложенческий pub/sub в Spring: ApplicationEventPublisher, @EventListener (синхронный), @Async + @EventListener (асинхронный), @TransactionalEventListener (привязка к фазам транзакции — BEFORE_COMMIT, AFTER_COMMIT, AFTER_ROLLBACK). Как использовать для domain events.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/events/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring AOP: когда нужен, @Aspect, ограничения</title>
<link>https://vikulin-va.ru/spring/aop/</link>
<description>Aspect-Oriented Programming в Spring: что такое pointcut/advice/aspect, как Spring инструментирует бины через прокси (JDK proxy vs CGLIB), типичные кейсы (логирование, метрики, retry, авторизация), ограничения (final-методы, self-invocation, не-Spring-бины).</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/aop/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring Security: фильтры, AuthN, AuthZ, OAuth2</title>
<link>https://vikulin-va.ru/spring/security/</link>
<description>Архитектура Spring Security: SecurityFilterChain, аутентификация vs авторизация, OAuth2 Resource Server (валидация JWT), OAuth2 Client (получение токена), method security (@PreAuthorize/@PostAuthorize), CSRF, session management, типичные конфигурации для REST-сервиса.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/security/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring Testing: @SpringBootTest, слайсы, TestContainers</title>
<link>https://vikulin-va.ru/spring/testing/</link>
<description>Пирамида тестов в Spring: unit-тесты без контекста, слайсы (@WebMvcTest, @DataJpaTest, @JsonTest), полный интеграционный @SpringBootTest, MockMvc и WebTestClient, тестирование транзакций и rollback, TestContainers для реальной БД/Kafka/RabbitMQ.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/testing/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring Actuator, Micrometer, трейсинг</title>
<link>https://vikulin-va.ru/spring/actuator-observability/</link>
<description>Spring Boot Actuator: health, info, custom endpoints, security. Micrometer как абстракция над метриками (Counter, Timer, Gauge), connectors к Prometheus/CloudWatch/Datadog. Distributed tracing через Micrometer Tracing + OpenTelemetry. Структурированное логирование с correlation ID.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/actuator-observability/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>Spring Scheduled, Async, виртуальные потоки</title>
<link>https://vikulin-va.ru/spring/scheduled-and-async/</link>
<description>Spring @Scheduled (cron, fixedDelay, fixedRate) и @Async для асинхронных операций. Пулы потоков (TaskExecutor, TaskScheduler), стандартные ловушки (self-invocation, exception swallowing). Виртуальные потоки Java 21+ в Spring Boot 3.2+: что меняют, когда WebFlux всё ещё нужен.</description>
<guid isPermaLink="true">https://vikulin-va.ru/spring/scheduled-and-async/</guid>
<pubDate>Mon, 18 May 2026 09:08:39 GMT</pubDate>
</item>
<item>
<title>SOLID на примерах Spring</title>
<link>https://vikulin-va.ru/design-patterns/solid/</link>
<description>Пять принципов SOLID на примерах Spring: как фреймворк воплощает SRP, OCP, LSP, ISP, DIP и как применять их в своём коде — от толстого @Service к Handler-ам и стратегиям.</description>
<guid isPermaLink="true">https://vikulin-va.ru/design-patterns/solid/</guid>
<pubDate>Sat, 6 Jun 2026 15:45:44 GMT</pubDate>
</item>
<item>
<title>Паттерны GoF в Spring: все 23 с примерами</title>
<link>https://vikulin-va.ru/design-patterns/gof/</link>
<description>Все 23 паттерна GoF на примерах Spring: Proxy в @Transactional, Strategy в PasswordEncoder, Observer в @EventListener. Какие пишут руками, какие дал фреймворк, какие вытеснил язык.</description>
<guid isPermaLink="true">https://vikulin-va.ru/design-patterns/gof/</guid>
<pubDate>Sat, 6 Jun 2026 15:45:44 GMT</pubDate>
</item>
<item>
<title>GRASP на примерах Spring</title>
<link>https://vikulin-va.ru/design-patterns/grasp/</link>
<description>Девять принципов GRASP на Java/Spring: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations.</description>
<guid isPermaLink="true">https://vikulin-va.ru/design-patterns/grasp/</guid>
<pubDate>Sat, 6 Jun 2026 15:55:00 GMT</pubDate>
</item>
<item>
<title>DRY, KISS, YAGNI и другие инженерные принципы</title>
<link>https://vikulin-va.ru/design-patterns/principles/</link>
<description>Девять инженерных принципов на Java/Spring: DRY, KISS, YAGNI, Separation of Concerns, Law of Demeter, композиция вместо наследования, Fail Fast, бритва Оккама.</description>
<guid isPermaLink="true">https://vikulin-va.ru/design-patterns/principles/</guid>
<pubDate>Sat, 6 Jun 2026 15:55:00 GMT</pubDate>
</item>
<item>
<title>Elasticsearch fundamentals: inverted index, cluster, shards, mapping, analyzers</title>
<link>https://vikulin-va.ru/elasticsearch/fundamentals/</link>
<description>Как устроен Elasticsearch: inverted index как основа быстрого поиска, segments и refresh interval, near-real-time природа, cluster (master/data/coordinating), primary и replica shards, mapping (dynamic vs explicit), analyzers (standard, ru, ngram). Без привязки к языку клиента.</description>
<guid isPermaLink="true">https://vikulin-va.ru/elasticsearch/fundamentals/</guid>
<pubDate>Mon, 18 May 2026 18:27:54 GMT</pubDate>
</item>
<item>
<title>Elasticsearch Query DSL и relevance scoring</title>
<link>https://vikulin-va.ru/elasticsearch/queries-and-relevance/</link>
<description>Query DSL Elasticsearch: match/term/range/bool, разница между query context и filter context, scoring через BM25, boosting полей, function_score, фасеты через aggregations, типичные запросы каталога товаров. Без привязки к языку клиента.</description>
<guid isPermaLink="true">https://vikulin-va.ru/elasticsearch/queries-and-relevance/</guid>
<pubDate>Mon, 18 May 2026 18:27:54 GMT</pubDate>
</item>
<item>
<title>Spring Data Elasticsearch: клиент, репозитории, индексация, CDC</title>
<link>https://vikulin-va.ru/elasticsearch/spring-data-elasticsearch/</link>
<description>spring-data-elasticsearch: ElasticsearchOperations vs ElasticsearchRepository, маппинг entity через @Document, bulk-индексация, паттерны синхронизации PostgreSQL/MongoDB → Elasticsearch (dual write, transactional outbox, CDC через Debezium → Kafka → ES), типичные ловушки.</description>
<guid isPermaLink="true">https://vikulin-va.ru/elasticsearch/spring-data-elasticsearch/</guid>
<pubDate>Mon, 18 May 2026 18:27:54 GMT</pubDate>
</item>
<item>
<title>Elasticsearch operations: ILM, snapshots, hot/warm/cold, sizing, мониторинг</title>
<link>https://vikulin-va.ru/elasticsearch/operations/</link>
<description>Эксплуатация Elasticsearch в production: Index Lifecycle Management (ILM) для time-based данных, snapshots в S3/GCS, hot/warm/cold/frozen tiers, force merge, sizing (heap, shards, RAM), мониторинг через Prometheus exporter, типичные оперативные ловушки.</description>
<guid isPermaLink="true">https://vikulin-va.ru/elasticsearch/operations/</guid>
<pubDate>Mon, 18 May 2026 18:27:54 GMT</pubDate>
</item>
<item>
<title>S3 fundamentals: bucket, object, key, storage classes, presigned URLs, multipart</title>
<link>https://vikulin-va.ru/object-storage/fundamentals/</link>
<description>Модель S3: bucket / object / key, эталонная семантика и eventual consistency (с 2020 — strong read-after-write), storage classes (Standard / IA / Glacier), versioning, encryption (SSE-S3, SSE-KMS, SSE-C), lifecycle policies, presigned URLs для прямой загрузки клиентом, multipart upload.</description>
<guid isPermaLink="true">https://vikulin-va.ru/object-storage/fundamentals/</guid>
<pubDate>Mon, 18 May 2026 18:50:26 GMT</pubDate>
</item>
<item>
<title>Spring + AWS SDK v2 для S3: интеграция, паттерны, MinIO</title>
<link>https://vikulin-va.ru/object-storage/spring-and-aws-sdk/</link>
<description>Интеграция Spring с S3 через AWS SDK v2: S3Client / S3AsyncClient / S3TransferManager, конфигурация для AWS S3 / MinIO / Yandex Object Storage / R2, паттерны загрузки и скачивания, presigned URLs из Spring, Outbox для атомарных операций «БД + S3», тесты с MinIO в Testcontainers.</description>
<guid isPermaLink="true">https://vikulin-va.ru/object-storage/spring-and-aws-sdk/</guid>
<pubDate>Mon, 18 May 2026 18:50:26 GMT</pubDate>
</item>
<item>
<title>S3 operations: backup, replication, lifecycle, costs, monitoring</title>
<link>https://vikulin-va.ru/object-storage/operations/</link>
<description>Эксплуатация object storage в production: стратегии резервного копирования (S3 как backup-target и backup для самого S3), cross-region replication, lifecycle policies, оценка стоимости (storage + requests + egress), мониторинг (CloudWatch metrics, доступ через access logs), типичные оперативные проблемы и инциденты.</description>
<guid isPermaLink="true">https://vikulin-va.ru/object-storage/operations/</guid>
<pubDate>Mon, 18 May 2026 18:50:26 GMT</pubDate>
</item>
<item>
<title>ClickHouse Fundamentals: колоночное хранение, MergeTree, OLAP vs OLTP</title>
<link>https://vikulin-va.ru/clickhouse/fundamentals/</link>
<description>Как устроен ClickHouse: колоночное хранение и сжатие, parts и merges в MergeTree, разреженный первичный индекс, семейство движков. Когда ClickHouse дополняет PostgreSQL.</description>
<guid isPermaLink="true">https://vikulin-va.ru/clickhouse/fundamentals/</guid>
<pubDate>Sat, 6 Jun 2026 16:23:44 GMT</pubDate>
</item>
<item>
<title>ClickHouse: моделирование схемы, запросы, materialized views</title>
<link>https://vikulin-va.ru/clickhouse/modeling-and-queries/</link>
<description>Проектирование таблиц ClickHouse: выбор ORDER BY и PARTITION BY, типы, агрегатные идиомы, materialized views, дедупликация через ReplacingMergeTree, антипаттерны.</description>
<guid isPermaLink="true">https://vikulin-va.ru/clickhouse/modeling-and-queries/</guid>
<pubDate>Sat, 6 Jun 2026 16:23:44 GMT</pubDate>
</item>
<item>
<title>ClickHouse из Java/Spring: JDBC, батчи, пайплайн из PostgreSQL и Kafka</title>
<link>https://vikulin-va.ru/clickhouse/java-spring-integration/</link>
<description>ClickHouse из Spring Boot: JDBC и второй DataSource, батчевая вставка и идемпотентность, пайплайн PostgreSQL → outbox → Kafka → ClickHouse, Testcontainers.</description>
<guid isPermaLink="true">https://vikulin-va.ru/clickhouse/java-spring-integration/</guid>
<pubDate>Sat, 6 Jun 2026 16:23:44 GMT</pubDate>
</item>
<item>
<title>ClickHouse Operations: репликация, шардинг, TTL, мониторинг</title>
<link>https://vikulin-va.ru/clickhouse/operations/</link>
<description>Эксплуатация ClickHouse: ReplicatedMergeTree и Keeper, шардинг через Distributed, TTL и многоуровневое хранение, бэкапы, system-таблицы, типичные инциденты.</description>
<guid isPermaLink="true">https://vikulin-va.ru/clickhouse/operations/</guid>
<pubDate>Sat, 6 Jun 2026 16:23:44 GMT</pubDate>
</item>
<item>
<title>Codegen jOOQ из живой схемы PostgreSQL</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/codegen/</link>
<description>Как настроить codegen jOOQ так, чтобы сгенерированные типы не расходились с реальной базой: Liquibase + Testcontainers + introspection вместо xml/ddl, OffsetDateTime для timestamptz, forced types, fluent setters. Раскрытие правил R-JOOQ-CFG-1..7 и R-JOOQ-CFG-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/codegen/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Repository pattern в jOOQ</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/repository-pattern/</link>
<description>Что такое Repository в подходе UCP, как разделять domain-интерфейс и jOOQ-реализацию, почему конструкторное внедрение через @RequiredArgsConstructor, что нельзя класть в репозиторий. Раскрытие правил R-JOOQ-REPO-1..6 и R-JOOQ-REPO-X1..X4 с примерами на доменах Order и Product.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/repository-pattern/</guid>
<pubDate>Mon, 25 May 2026 15:20:25 GMT</pubDate>
</item>
<item>
<title>DSLContext в jOOQ — Spring-bean, один на ApplicationContext</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/dslcontext/</link>
<description>Что такое DSLContext в jOOQ, почему он Spring-bean и singleton, когда менять Settings и RecordMapperProvider, что нельзя делать руками (DSL.using, хранение в state репозитория). Раскрытие правил R-JOOQ-CTX-1..3 и R-JOOQ-CTX-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/dslcontext/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Построение запросов в jOOQ</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/query-building/</link>
<description>Как писать читаемые SQL-запросы через jOOQ DSL: static imports, выбор между selectFrom и select(...), fetch-методы под цель (fetchOptional / fetchOne / fetchExists / fetchCount), позиционные bind-параметры, EXISTS-подзапросы. Раскрытие правил R-JOOQ-QRY-1..7 и R-JOOQ-QRY-X1..X6.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/query-building/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Multiset в jOOQ — eager-fetch вложенных коллекций одним запросом</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/multiset/</link>
<description>Как доставать вложенные коллекции в jOOQ через multiset() без N+1, как организовать константы alias-keys, как извлекать nested-результаты через RecordMappingUtils, когда multiset не подходит и нужен batch-fetch. Раскрытие правил R-JOOQ-MS-1..4 и R-JOOQ-MS-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/multiset/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Filter Builders в jOOQ — динамические WHERE без if-цепочек</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/filter-builders/</link>
<description>Как организовать сложные WHERE с динамическими условиями в jOOQ: &lt;X&gt;FilterConditionBuilder как Spring-компонент, &lt;X&gt;Filter как immutable record в core, FilterConditionHelper с andIfNotNull / andIfNotEmpty, EXISTS для cross-table, единственное место знания о Filter ↔ jOOQ-таблицах. Раскрытие правил R-JOOQ-FLT-1..6 и R-JOOQ-FLT-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/filter-builders/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Маппинг record ↔ domain в jOOQ — plain Java, не MapStruct</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/record-domain-mapping/</link>
<description>Почему маппер в jOOQ — это plain Java @Component, а не MapStruct interface. Как организовать assembleAggregate из плоских POJO, делегацию child-маппера, JSONB через JooqJsonbHelper, enum-конверсию. Почему forcedType вытаскивает OffsetDateTime в codegen-time. Раскрытие правил R-JOOQ-MAP-1..7 и R-JOOQ-MAP-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/record-domain-mapping/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Пагинация в jOOQ — offset, cursor, PaginationView</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/pagination/</link>
<description>Как организовать offset-based и cursor-based пагинацию в jOOQ: PaginationView&lt;T&gt; как domain-record, выбор между offset/cursor, отдельный fetchCount для total, opaque-cursor токены. Когда не считать total. Раскрытие правил R-JOOQ-PAG-1..5 и R-JOOQ-PAG-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/pagination/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Lock-режимы в jOOQ — SelectMode, FOR UPDATE, SKIP LOCKED</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/lock-modes/</link>
<description>Как организовать lock-режимы в репозиториях jOOQ через SelectMode enum, почему forUpdate() обязан жить внутри @Transactional, что такое SKIP LOCKED для batch-схедулеров, почему optimistic locking — через version-колонку, не Settings. Раскрытие правил R-JOOQ-LCK-1..4 и R-JOOQ-LCK-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/lock-modes/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Транзакции в jOOQ — @Transactional на handler'е</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/transactions/</link>
<description>Где живут границы транзакций в UCP: @Transactional на UseCaseHandler, не на репозитории, не на сервисе. @Transactional(readOnly = true) на query-handler. Когда менять isolation level. Почему dslContext.transaction(...) внутри Spring-транзакции — антипаттерн. Раскрытие правил R-JOOQ-TX-1..3 и R-JOOQ-TX-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/transactions/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>View-репозитории в jOOQ — read-проекции отдельно от агрегата</title>
<link>https://vikulin-va.ru/standards/backend/java/jooq/view-repositories/</link>
<description>Зачем выделять &lt;X&gt;ViewRepository рядом с &lt;X&gt;Repository, как организовать read-DTO в core, чем view отличается от агрегата, почему не стоит перегружать основной репозиторий методами findSummaries/findForExport. Раскрытие правил R-JOOQ-VIEW-1..3 и R-JOOQ-VIEW-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/jooq/view-repositories/</guid>
<pubDate>Mon, 25 May 2026 15:44:54 GMT</pubDate>
</item>
<item>
<title>Базовые правила — синхронные тесты и AAA-структура</title>
<link>https://vikulin-va.ru/standards/backend/java/test-strategy/basics/</link>
<description>Базовые правила интеграционных тестов UCP: тест быстрый и детерминированный — Awaitility/Thread.sleep признак инфраструктурного smoke, не бизнес-логики. Интеграционный = полный Spring + PostgreSQL + HTTP. Внешние HTTP — WireMock или @MockitoBean. Kafka/Redis заменяются на Outbox-проверку или выключаются профилем. Все тесты синхронные — никаких CompletableFuture.get(), Awaitility, Thread.sleep; время и UUID детерминированные через @MockitoBean. Один тест — один сценарий, AAA-структура. Раскрытие TS-1..TS-3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/test-strategy/basics/</guid>
<pubDate>Tue, 26 May 2026 09:39:15 GMT</pubDate>
</item>
<item>
<title>BaseIntegrationTest — платформенный + доменный base</title>
<link>https://vikulin-va.ru/standards/backend/java/test-strategy/base-integration-test/</link>
<description>BaseIntegrationTest: один платформенный PlatformBaseIntegrationTest + по одному доменному base на каждый Bounded Context. @ServiceConnection (Spring Boot 3.1+) — Spring сам прокидывает свойства в spring.datasource.* без @DynamicPropertySource. @TestInstance(Lifecycle.PER_CLASS) — дорогой setup в @BeforeAll без static. Время и UUID — @MockitoBean DateTimeService + UuidGenerator. @Import(TestJwtConfiguration.class) даёт фейковый JWT + TestHttpHeaders.withSuccessToken(). Раскрытие TS-4..TS-8.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/test-strategy/base-integration-test/</guid>
<pubDate>Tue, 26 May 2026 09:39:15 GMT</pubDate>
</item>
<item>
<title>DatabasePreparer — fluent setup БД через DSLContext</title>
<link>https://vikulin-va.ru/standards/backend/java/test-strategy/database-preparer/</link>
<description>DatabasePreparer: на каждый Bounded Context — свой &lt;Domain&gt;DatabasePreparer как @Component-обёртка над DSLContext. Три группы методов: clear*() очистка, create*(...) вставка, prepare() запуск очереди. Не пересоздаём схему между тестами — только DELETE нужных таблиц (миллисекунды вместо секунд). Порядок вызовов = порядок исполнения: при наличии FK сначала чистим зависимые, последними создаём родительские. Раскрытие TS-9..TS-11.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/test-strategy/database-preparer/</guid>
<pubDate>Tue, 26 May 2026 09:39:15 GMT</pubDate>
</item>
<item>
<title>TestObjectGenerator — fluent builders сущностей с разумными дефолтами</title>
<link>https://vikulin-va.ru/standards/backend/java/test-strategy/test-object-generator/</link>
<description>TestObjectGenerator: на каждую POJO-таблицу — builder с with*-методами и generate(). Разумные дефолты (UUID.randomUUID(), текущее время с обнулёнными наносекундами); в тесте перезаписываем только то что важно для сценария. withNano(0) обязательно при сравнении OffsetDateTime в БД — PostgreSQL timestamp хранит миллисекунды, Java наносекунды; без обнуления сравнение даст false negative. Раскрытие TS-12..TS-14.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/test-strategy/test-object-generator/</guid>
<pubDate>Tue, 26 May 2026 09:39:15 GMT</pubDate>
</item>
<item>
<title>Один тест — структура, имена и TestRestTemplate</title>
<link>https://vikulin-va.ru/standards/backend/java/test-strategy/one-test/</link>
<description>Структура одного integration-теста: extends &lt;Domain&gt;BaseIntegrationTest, инжектит TestRestTemplate и DatabasePreparer. Имена: &lt;action&gt;_when&lt;Condition&gt;_&lt;expectedResult&gt; с @DisplayName и BR-кодом. HTTP через TestRestTemplate.exchange(...) — точный контроль над методом, заголовками, телом; MockMvc для unit-тестов контроллера без БД. JWT через TestHttpHeaders.withSuccessToken() или специализированные хелперы — не собираем токены руками. Раскрытие TS-15..TS-18.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/test-strategy/one-test/</guid>
<pubDate>Tue, 26 May 2026 09:39:15 GMT</pubDate>
</item>
<item>
<title>Kafka, Redis, async — по умолчанию НЕТ</title>
<link>https://vikulin-va.ru/standards/backend/java/test-strategy/no-kafka-redis-async/</link>
<description>Kafka, Redis, async в integration-тестах UCP: не поднимаем Kafka — события остаются в Outbox-таблице, проверяем через DSLContext. Redis не поднимаем — профиль integration-test ставит spring.cache.type=none. Kafka listener (idempotent consumer) тестируем напрямую как Spring-бин: eventHandler.handle(testEvent) без EmbeddedKafka. Async/Saga (@TransactionalEventListener AFTER_COMMIT) переводим в синхрон через профиль теста или ручной commit + явный вызов handler-а. Раскрытие TS-19..TS-22.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/test-strategy/no-kafka-redis-async/</guid>
<pubDate>Tue, 26 May 2026 09:39:15 GMT</pubDate>
</item>
<item>
<title>Внешние HTTP — WireMock в BaseIntegrationTest</title>
<link>https://vikulin-va.ru/standards/backend/java/test-strategy/wiremock-external-http/</link>
<description>Внешние HTTP в integration-тестах: WireMock в BaseIntegrationTest через @RegisterExtension с dynamic port и @DynamicPropertySource. Стабы пишем в самом тесте, не в общих mappings/*.json — видно на что опирается тест. Если внешний клиент @FeignClient можно мокать через @MockitoBean, но WireMock предпочтительнее — проверяет ещё сериализацию HTTP, заголовки, retry, timeout. Раскрытие TS-23..TS-25.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/test-strategy/wiremock-external-http/</guid>
<pubDate>Tue, 26 May 2026 09:39:15 GMT</pubDate>
</item>
<item>
<title>Что НЕ покрывается интеграционными — unit, @WebMvcTest и E2E</title>
<link>https://vikulin-va.ru/standards/backend/java/test-strategy/what-is-not-covered/</link>
<description>Что НЕ покрывается интеграционными: чистая бизнес-логика агрегата — unit-тест без Spring (new Order, order.confirm()), самые быстрые. Контроллер + сериализация JSON без БД — @WebMvcTest + MockMvc. E2E через настоящие Kafka / внешние сервисы — отдельная группа @Tag(e2e), отдельный CI-этап, ≤ 5-10 тестов на сервис. Пирамида: много unit → integration → мало E2E; каждый слой своя цель и стоимость. Раскрытие TS-26..TS-28.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/java/test-strategy/what-is-not-covered/</guid>
<pubDate>Tue, 26 May 2026 09:39:15 GMT</pubDate>
</item>
<item>
<title>URL и ресурсы — kebab-case, множественное число и HTTP-методы</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/url-and-resources/</link>
<description>URL и ресурсы REST: 4 принципа (предсказуемость, единообразие, читаемость, стабильность); HATEOAS-ссылки в теле запрещены, навигация в OpenAPI. Формат пути: kebab-case, lowercase, без trailing slash, без расширений; служебные эндпоинты (/health, /ready) вне /api/v1/. Коллекции — множественное число; singleton — единственное. HTTP-методы по семантике. Максимум 2 уровня вложенности; ID в пути не в теле; path-переменная в дизайне URL — {id}. Раскрытие R-PRIN-1..4, R-URL-1..3, R-RES-1..3, R-MTH-1..6, R-NEST-1..4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/url-and-resources/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>Alias и Action-эндпоинты — me, latest, default и доменные команды</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/alias-and-actions/</link>
<description>Alias-сегменты REST: me только в эндпоинтах принимающих и свой и чужой ID; временные/порядковые (latest, current, next) и логические (default, primary, active) — для singleton-выборки. Action-эндпоинты для команд не укладывающихся в CRUD: POST /orders/{id}/confirm, имя — глагол в инфинитиве, метод POST всегда, параметры в теле. Запреты: me где endpoint singleton; me без users/ префикса; существительное или причастие в имени action; PUT для action. Раскрытие R-ALIAS-1..3, R-ACT-1..4 и X-кодов.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/alias-and-actions/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>Версионирование — v1/v2 в URL и breaking vs non-breaking</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/versioning/</link>
<description>Версионирование REST: версия в URL-пути (формат v + целое; /api/v1/orders); /api префикс обязателен. Новая версия только при breaking change. Клиент ОБЯЗАН игнорировать неизвестные enum-значения и поля в ответе — на этом основано: добавление optional поля = non-breaking. Breaking: удаление/переименование поля, изменение типа, удаление enum-значения, изменение HTTP-метода/URL. Non-breaking: добавление optional поля, enum-значения, endpoint, ослабление валидации. Запреты: минорная или дата-версия в пути; версия в query; endpoint без /api или без версии; новая версия для optional поля. Раскрытие R-VER-1..6 и X-кодов.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/versioning/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>Query-параметры и пагинация — offset 1-based, cursor и POST /search</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/query-params/</link>
<description>Query-параметры REST: camelCase; фильтрация по полю (?status=CONFIRMED); диапазоны через From/To. Offset-based — page (1-based!) + size. Cursor-based — cursor (opaque) + size. Сортировка sort=поле,direction. Множественные значения — повтор параметра (style=form, explode=true). Сложные запросы — POST /resources/search с JSON body. Запреты: snake_case или PascalCase; page=0 в публичном контракте; comma-separated значения; бизнес-логика в query; парсинг cursor на клиенте. Раскрытие R-QRY-1..9 и X-кодов.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/query-params/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>JSON и формат ответов — camelCase, ISO 8601, без envelope и null</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/json-and-responses/</link>
<description>JSON REST: camelCase, ISO 8601, enum UPPER_SNAKE_CASE, коллекции — множественное, ID-суффикс. null в PATCH body — команда удалить поле; null в response 2xx запрещён (отсутствие = нет в JSON). Единичный ресурс — плоский без обёртки; коллекция — content + пагинация; создание 201 + Location; обновление 200; удаление 204; action 200. Пустые коллекции — []. Запреты: null в response, пустые строки, nullable=true в OpenAPI, envelope-обёртка {success, data}. Раскрытие R-FLD-1..7, R-RSP-1..8 и X-кодов.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/json-and-responses/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>Заголовки и трассировка — Idempotency-Key и traceparent W3C</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/headers/</link>
<description>Заголовки REST: стандартные по назначению. Кастомные с доменным префиксом единым для всех сервисов проекта (Shop-Request-Id). Idempotency-Key для POST безопасных при retry. traceparent (W3C Trace Context): 00-{trace-id}-{parent-id}-{flags}; если клиент прислал — используем trace-id, создаём новый parent-id; иначе генерируем. trace-id используется как traceId в теле ошибки RFC 9457. Запреты: X- префикс в кастомных headers (устарел RFC 6648). Раскрытие R-HDR-1..4 и X-кодов.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/headers/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>Ошибки RFC 9457 — Problem Details, URN type и violations</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/errors/</link>
<description>Ошибки REST по RFC 9457 Problem Details: type (URI/URN категории), status, title, detail, instance, traceId, code (UPPER_SNAKE_CASE enum). type — URL на документацию или urn:problem:&lt;service&gt;:&lt;code&gt;. Content-Type — application/problem+json. Валидация: 400 + VALIDATION_ERROR + violations массив (field dot-notation, message, все ошибки за раз). HTTP-коды: 400/500 всегда, 401/403 при auth, 404 по ID, 409 conflict, 410 deprecated, 429 rate limit. Запреты: application/json для ошибки; type=about:blank; коды вне списка; stack traces в 500. Раскрытие R-ERR-1..9 и X-кодов.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/errors/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>Rate limiting, файлы, deprecation — 429, multipart, Sunset</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/rate-limiting-files-deprecation/</link>
<description>Rate limiting REST: 429 + Retry-After + RateLimit-Limit/Remaining/Reset в каждом успешном response. Файлы — POST multipart/form-data на вложенный ресурс; скачивание — GET с бинарным Content-Type и Content-Disposition. Deprecation: deprecated=true в OpenAPI + Sunset (RFC 8594) + Deprecation: true + Link rel=successor-version; после Sunset → 410 Gone. Запреты: 429 без headers; file upload через JSON Base64; deprecated без Sunset header. Раскрытие R-RATE-1..3, R-FILE-1..5, R-DEP-1..3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/rate-limiting-files-deprecation/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>Batch, async, локализация — partial success, 202 polling, Accept-Language</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/batch-async-localization/</link>
<description>Batch-операции REST: поэлементно (partial success); POST /resources/batch; request {items: [...]}; response 200 + results (index, status, error) + summary. Max-size в OpenAPI; превышение → 400 BATCH_SIZE_EXCEEDED. Async через polling: 202 Accepted + Location + taskId/status/statusUrl; статусы PENDING/PROCESSING/COMPLETED/FAILED; resultUrl или error. Локализация через Accept-Language — локализуются detail и violations.message. Запреты: локализация code enum, title, type URI, JSON-полей. Раскрытие R-BATCH-1..5, R-ASYNC-1..4, R-LOC-1..3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/batch-async-localization/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>OpenAPI-метаданные и сводка антипаттернов</title>
<link>https://vikulin-va.ru/standards/backend/rest-api/java/openapi-and-antipatterns/</link>
<description>OpenAPI-метаданные REST: operationId уникальный в camelCase, формат действие+ресурс (createOrder, confirmOrder). Группировка через tags — один на ресурс, множественное число с заглавной (Orders). Параметры пути в OpenAPI уникальны ({orderId}, {itemId}) — требование Swagger/Redoc; в дизайне URL — {id}. summary до 80 символов; description если логика неочевидна. Сводка антипаттернов из всех разделов гайда — единая checkin-таблица: URL (X1..X4), версионирование, query, JSON, headers, errors, rate-limiting, deprecation, alias-actions, локализация. Раскрытие R-OAS-1..4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/rest-api/java/openapi-and-antipatterns/</guid>
<pubDate>Tue, 26 May 2026 11:01:22 GMT</pubDate>
</item>
<item>
<title>Иерархия исключений в Spring Boot — Domain / Validation / Integration / Technical</title>
<link>https://vikulin-va.ru/standards/backend/error-handling/java/exception-hierarchy/</link>
<description>Четыре базовых типа RuntimeException в UCP: DomainException, ValidationException, IntegrationException, TechnicalException. Где они живут, как именовать, почему конструкторы фиксируют контекст. Запрет throw new RuntimeException и IllegalStateException в доменном коде. Раскрытие правил R-ERR-HIER-1..5 и R-ERR-HIER-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/error-handling/java/exception-hierarchy/</guid>
<pubDate>Mon, 25 May 2026 16:11:08 GMT</pubDate>
</item>
<item>
<title>Где throw, где catch — три точки catch в Spring Boot</title>
<link>https://vikulin-va.ru/standards/backend/error-handling/java/where-throw-where-catch/</link>
<description>Throw — везде, где нужно. Catch — ровно в трёх местах: @RestControllerAdvice, out-adapter, резильянс-обёртка. Главный антипаттерн — silent catch (Exception e). Раскрытие правил R-ERR-WHERE-1..3 и R-ERR-WHERE-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/error-handling/java/where-throw-where-catch/</guid>
<pubDate>Mon, 25 May 2026 16:11:08 GMT</pubDate>
</item>
<item>
<title>Mapping исключений в ProblemDetails (RFC 9457)</title>
<link>https://vikulin-va.ru/standards/backend/error-handling/java/problem-details-mapping/</link>
<description>Как мапить иерархию исключений в HTTP-ответы по RFC 9457: DomainException → 409/422, ValidationException → 400, IntegrationException → 502/503/504, TechnicalException → 500. Что класть в type / detail / properties, что НЕ класть. Раскрытие правил R-ERR-MAP-1..5 и R-ERR-MAP-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/error-handling/java/problem-details-mapping/</guid>
<pubDate>Mon, 25 May 2026 16:11:08 GMT</pubDate>
</item>
<item>
<title>Логирование исключений в Spring Boot — WARN / ERROR, один раз, на edge</title>
<link>https://vikulin-va.ru/standards/backend/error-handling/java/exception-logging/</link>
<description>Какой log-level использовать: DomainException → WARN, IntegrationException → WARN/ERROR, TechnicalException → ERROR. Логируем один раз — на edge. Запрет двойного логирования и log.error без объекта e. Раскрытие правил R-ERR-LOG-1..4 и R-ERR-LOG-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/error-handling/java/exception-logging/</guid>
<pubDate>Mon, 25 May 2026 16:11:08 GMT</pubDate>
</item>
<item>
<title>Retry / no-retry семантика по типу исключения</title>
<link>https://vikulin-va.ru/standards/backend/error-handling/java/retry-semantics/</link>
<description>Какие исключения retry-safe, а какие — нет: DomainException и ValidationException никогда не retry, IntegrationException — при идемпотентности, TechnicalException обычно retry. HTTP 4xx — не retry, 5xx и timeout — retry safe только при Idempotency-Key. Раскрытие правил R-ERR-RETRY-1..3 и R-ERR-RETRY-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/error-handling/java/retry-semantics/</guid>
<pubDate>Mon, 25 May 2026 16:11:08 GMT</pubDate>
</item>
<item>
<title>Result-types vs exceptions в Spring Boot — когда и где</title>
<link>https://vikulin-va.ru/standards/backend/error-handling/java/result-types-vs-exceptions/</link>
<description>Когда Result&lt;T, E&gt; разрешён (чисто-функциональные модули — парсеры, calc-engines), когда нет (UseCase Handler → Domain → Adapter цепочка). Почему глобальная замена исключений на Result в Java без pattern-matching — те же яйца, в профиль. Раскрытие правил R-ERR-RESULT-1..2 и R-ERR-RESULT-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/error-handling/java/result-types-vs-exceptions/</guid>
<pubDate>Mon, 25 May 2026 16:11:08 GMT</pubDate>
</item>
<item>
<title>Observability ошибок — метрики, trace, алёрты</title>
<link>https://vikulin-va.ru/standards/backend/error-handling/java/observability-errors/</link>
<description>Метрика app_errors_total с type/exception, OpenTelemetry span как ERROR, алёрты на необычные паттерны (рост unexpected = новый баг, рост integration = внешка деградирует), а не на каждый exception. Запрет алёрта на любой exception в логах. Раскрытие правил R-ERR-OBS-1..3 и R-ERR-OBS-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/error-handling/java/observability-errors/</guid>
<pubDate>Mon, 25 May 2026 16:11:08 GMT</pubDate>
</item>
<item>
<title>JVM/Spring конфигурация — server.shutdown=graceful и ApplicationAvailability</title>
<link>https://vikulin-va.ru/standards/backend/graceful-shutdown/java/jvm-spring-config/</link>
<description>Spring Boot graceful shutdown: server.shutdown=graceful обязательно — без этого Tomcat/Netty forceShutdown() сразу на SIGTERM, активные HTTP-запросы получают 502. spring.lifecycle.timeout-per-shutdown-phase 30s — баланс между «успеть дрейнить» и «не SIGKILL». Hook на SIGTERM ставит ApplicationAvailability.readinessState OUT_OF_SERVICE первым. management.health.{livenessstate,readinessstate}.enabled true. Запреты: свой AtomicBoolean shuttingDown — не интегрируется с health-эндпоинтами, k8s не узнает. Раскрытие R-SHUT-CFG-1..4 и R-SHUT-CFG-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/graceful-shutdown/java/jvm-spring-config/</guid>
<pubDate>Tue, 26 May 2026 08:06:00 GMT</pubDate>
</item>
<item>
<title>HTTP drain — preStop sleep и долгие endpoints</title>
<link>https://vikulin-va.ru/standards/backend/graceful-shutdown/java/http-drain/</link>
<description>HTTP drain: in-flight HTTP-запросы дожимаются до response, новые принимаются до switch readiness в OUT_OF_SERVICE. preStop hook со sleep 10 обязателен даже при правильном Spring graceful — k8s запускает SIGTERM до того как kube-proxy на других нодах распространит «убрать pod из endpoints», без preStop 5-15 секунд новый трафик идёт на pod который уже shutdown. Долгие синхронные endpoints (&gt;10 сек) — @Async + Idempotency-Key либо 202 Accepted + polling. Запреты: WebServerCustomizer с awaitTermination(0) — аннулирует graceful. Раскрытие R-SHUT-HTTP-1..3 и R-SHUT-HTTP-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/graceful-shutdown/java/http-drain/</guid>
<pubDate>Tue, 26 May 2026 08:06:00 GMT</pubDate>
</item>
<item>
<title>Kafka shutdown — listener container stop и producer flush</title>
<link>https://vikulin-va.ru/standards/backend/graceful-shutdown/java/kafka-shutdown/</link>
<description>Kafka shutdown в Spring: @KafkaListener дожимает текущий batch и коммитит offset перед остановкой через ConcurrentMessageListenerContainer.stop(timeout) с настройкой spring.kafka.listener.shutdown-timeout 20s. Listener не запускает долгий cascade — не уложится в shutdown-timeout, cascade в outbox/async-flow. ack-mode BATCH или RECORD явно, не MANUAL_IMMEDIATE без обоснования. Producer.flush() автоматически через KafkaTemplate.destroy(); raw KafkaProducer — обязательно producer.close(Duration.ofSeconds(15)). Запреты: enable.auto.commit=true — потеря сообщений. Раскрытие R-SHUT-KFK-1..4 и R-SHUT-KFK-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/graceful-shutdown/java/kafka-shutdown/</guid>
<pubDate>Tue, 26 May 2026 08:06:00 GMT</pubDate>
</item>
<item>
<title>БД и persistence — HikariCP в правильную фазу, активные транзакции</title>
<link>https://vikulin-va.ru/standards/backend/graceful-shutdown/java/db-and-persistence/</link>
<description>БД при graceful shutdown: HikariCP закрывается после Spring shutdown phases — дефолт Spring Boot правильный (DataSource.close() в последней фазе); не переопределять @PreDestroy на DataSource — может закрыть pool до завершения @Scheduled. Активные транзакции на SIGTERM: HTTP-handler в transaction → graceful HTTP дожимает; @Scheduled → ждать текущую итерацию; @KafkaListener → batch завершается; @Async — отдельная боль awaitTermination. Liquibase/Flyway — startup только. Запреты: DataSource.close() в кастомном @PreDestroy с @Order(LOWEST_PRECEDENCE). Раскрытие R-SHUT-DB-1..3 и R-SHUT-DB-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/graceful-shutdown/java/db-and-persistence/</guid>
<pubDate>Tue, 26 May 2026 08:06:00 GMT</pubDate>
</item>
<item>
<title>Scheduled / @Async / outbox — TaskScheduler shutdown и await-termination</title>
<link>https://vikulin-va.ru/standards/backend/graceful-shutdown/java/scheduled-async-outbox/</link>
<description>Graceful shutdown для Scheduled, @Async и outbox-relay: @Scheduled-методы завершают текущую итерацию через TaskScheduler.shutdown() с spring.task.scheduling.shutdown.await-termination=true и await-termination-period 25s. @Async-таски с долгим cascade опасны — ExecutorService default делает interrupt(); ThreadPoolTaskExecutor с setWaitForTasksToCompleteOnShutdown(true) и setAwaitTerminationSeconds(20). Outbox-relay завершает текущий batch (FOR UPDATE SKIP LOCKED атомарно), не начинает новый. Запреты: setWaitForTasksToCompleteOnShutdown(false) — частичные изменения в БД без rollback. Раскрытие R-SHUT-SCHED-1..3 и R-SHUT-SCHED-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/graceful-shutdown/java/scheduled-async-outbox/</guid>
<pubDate>Tue, 26 May 2026 08:06:00 GMT</pubDate>
</item>
<item>
<title>Kubernetes — terminationGracePeriodSeconds, probes, maxSurge</title>
<link>https://vikulin-va.ru/standards/backend/graceful-shutdown/java/kubernetes/</link>
<description>Kubernetes graceful: terminationGracePeriodSeconds 60 обязательно (не дефолт-30); preStop sleep не входит в этот бюджет. readinessProbe на /actuator/health/readiness, livenessProbe на /actuator/health/liveness — на shutdown нужен readiness=503 (убирает из endpoints), не liveness (рестартует pod). maxSurge 1 + maxUnavailable 0 — zero downtime rolling deploy. Запреты: отсутствие preStop — 5-15 секунд после SIGTERM kube-proxy ещё льёт трафик, гарантированные 502; terminationGracePeriodSeconds=30 с Spring graceful 30s — preStop 10s не помещается, SIGKILL посередине дрейна. Раскрытие R-SHUT-K8S-1..3 и R-SHUT-K8S-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/graceful-shutdown/java/kubernetes/</guid>
<pubDate>Tue, 26 May 2026 08:06:00 GMT</pubDate>
</item>
<item>
<title>Идемпотентность in-flight операций — защита от replay при SIGTERM</title>
<link>https://vikulin-va.ru/standards/backend/graceful-shutdown/java/idempotency-in-flight/</link>
<description>Идемпотентность in-flight при graceful shutdown: операции которые SIGTERM может прервать обязаны быть retry-safe. HTTP POST — Idempotency-Key обязателен (AUTH-19). Kafka-listener закоммитил offset но не завершил side-effect → replay создаёт дубль; защита: processed_event(event_id) в той же транзакции что и side-effect. Outbox-relay отправил в Kafka но не пометил published=true → следующий relay отправит повторно; защита: двух-фаза pending→publishing→published либо processed_event-дедуп на consumer-стороне. Запреты: money-операция без Idempotency-Key с @Retry — при SIGTERM в retry дважды списать. Раскрытие R-SHUT-IDEM-1 и R-SHUT-IDEM-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/graceful-shutdown/java/idempotency-in-flight/</guid>
<pubDate>Tue, 26 May 2026 08:06:00 GMT</pubDate>
</item>
<item>
<title>Бюджеты и observability — раскладка 60s budget и app_shutdown_duration</title>
<link>https://vikulin-va.ru/standards/backend/graceful-shutdown/java/budgets-and-observability/</link>
<description>Бюджет graceful shutdown: 60s total (cumulative) = preStop 10s + Spring graceful HTTP drain до 25s + TaskScheduler/@Async до 20s + Kafka listener до 15s = 70s max, но Spring выполняет phases частично параллельно, реальный wall clock 30-40s. Не помещается — сократить scope операций (batch Kafka 100→20), не увеличивать budget. Метрика app_shutdown_duration_seconds (gauge) + structured лог start/end. Лог причины SIGTERM — kubectl describe pod показывает событие, в коде только факт. Запреты: ERROR-уровень на normal shutdown events (HikariPool Shutdown initiated) — alert-канал заспамлен каждым деплоем. Раскрытие R-SHUT-OBS-1..3 и R-SHUT-OBS-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/graceful-shutdown/java/budgets-and-observability/</guid>
<pubDate>Tue, 26 May 2026 08:06:00 GMT</pubDate>
</item>
<item>
<title>SAST по коду — Error Prone, SpotBugs, FindSecBugs</title>
<link>https://vikulin-va.ru/standards/backend/security/java/sast/</link>
<description>SAST для Java/Spring: Error Prone обязателен через gradle-plugin, ловит на этапе компиляции EqualsHashCode, NullableDereference, мисьюз CompletableFuture, утечки try-with-resources. SpotBugs + FindSecBugs обязательны для production: общие баги + security-specific — SQLi, XSS, path traversal, weak crypto, XXE, hardcoded passwords. HIGH/CRITICAL → failOnError true; MEDIUM — комментарий ревьюера; LOW — игнор. Suppressions в config/spotbugs-exclude.xml с обязательным justify и сроком до 2026-MM-DD. Запреты: @SuppressFBWarnings без justification ≥ 30 символов. Раскрытие R-SEC-SAST-1..4 и R-SEC-SAST-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/security/java/sast/</guid>
<pubDate>Tue, 26 May 2026 07:54:04 GMT</pubDate>
</item>
<item>
<title>CVE в зависимостях — OWASP Dependency-Check и Renovate</title>
<link>https://vikulin-va.ru/standards/backend/security/java/dependency-cve/</link>
<description>CVE в зависимостях: OWASP Dependency-Check обязателен — сканирует runtime/test-зависимости против NIST NVD. Запускается на merge в main + nightly + release-tag, не на каждом PR. NVD_API_KEY обязателен — без ключа NVD-rate-limit убьёт CI. Renovate или Dependabot обязателен — auto-PR на minor/patch, major — manual review. CVSS ≥ 7.0 → failBuildOnCVSS=7.0 ломает сборку; 4.0-6.9 — отчёт + 30 дней; ниже — игнор. Suppressions с обязательным until= и notes. Запреты: подавление CVE без until= (бессрочное); snapshot-зависимости в production. Раскрытие R-SEC-DEP-1..4 и R-SEC-DEP-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/security/java/dependency-cve/</guid>
<pubDate>Tue, 26 May 2026 07:54:04 GMT</pubDate>
</item>
<item>
<title>Секреты в коде и истории — Gitleaks pre-commit и rotation</title>
<link>https://vikulin-va.ru/standards/backend/security/java/secrets-in-code/</link>
<description>Секреты: Gitleaks в pre-commit + CI, full history scan раз в неделю. Pre-commit hook через husky или pre-commit-framework — не как ручная инструкция README. Утечка → rotate сначала, удаление из истории опционально (GitHub уже проиндексировал, git rebase не помогает); rotation в течение часа от обнаружения. Запреты: секреты в application.yml — только через ${ENV_VAR}; .env в git (даже с пометкой example) — используй .env.example без значений. Раскрытие R-SEC-SECRET-1..3 и R-SEC-SECRET-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/security/java/secrets-in-code/</guid>
<pubDate>Tue, 26 May 2026 07:54:04 GMT</pubDate>
</item>
<item>
<title>Container/image-уязвимости — Trivy, non-root, digest-pin</title>
<link>https://vikulin-va.ru/standards/backend/security/java/container-image/</link>
<description>Container/image-уязвимости: Trivy обязателен для Docker-образов — сканирует base image, OS-пакеты, библиотеки; запускается в CI после сборки до push в registry. HIGH/CRITICAL → exit-code 1 + ignore-unfixed. Base image — eclipse-temurin:21-jre-alpine или distroless; никогда :latest без digest-pin. Non-root user USER 1000:1000 в конце Dockerfile — иначе CVE escape → root. HEALTHCHECK или K8s liveness/readiness обязательно. Запреты: USER root или отсутствие USER; :latest base image (сборка не воспроизводима). Раскрытие R-SEC-IMG-1..4 и R-SEC-IMG-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/security/java/container-image/</guid>
<pubDate>Tue, 26 May 2026 07:54:04 GMT</pubDate>
</item>
<item>
<title>Криптография в коде — BCrypt, AES-GCM, SecureRandom</title>
<link>https://vikulin-va.ru/standards/backend/security/java/crypto/</link>
<description>Криптография в Java: пароли — только BCryptPasswordEncoder с factor ≥ 12, никогда MD5/SHA1/SHA256 без salt. Random для security — только java.security.SecureRandom; java.util.Random только тесты и не-security код. Симметричное шифрование — AES-GCM (AES/GCM/NoPadding) с 12-байтным IV рандомным на каждый encrypt; не AES/ECB, не AES/CBC без MAC. TLS минимум 1.2. JWT verification — через oauth2ResourceServer().jwt(), вручную парсить (Jwts.parser без проверки подписи) критическая ошибка. Запреты: hardcoded ключи/IV в коде — Vault/KMS + env. Раскрытие R-SEC-CRYPTO-1..5 и R-SEC-CRYPTO-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/security/java/crypto/</guid>
<pubDate>Tue, 26 May 2026 07:54:04 GMT</pubDate>
</item>
<item>
<title>Реакция на findings — severity, SLA и suppressions со сроком</title>
<link>https://vikulin-va.ru/standards/backend/security/java/findings-response/</link>
<description>Реакция на security findings: CRITICAL — hotfix &lt; 24 часа; HIGH — патч в текущем спринте (≤ 2 недели); MEDIUM — отчёт + 30 дней; LOW — игнор. Suppressions имеют срок (until=...) — без срока finding считается долгом; раз в квартал автоматический отчёт просроченных. GitHub Code Scanning / SARIF — единый dashboard через GitHub Security tab без отдельной инфры. Baseline-механика: release блокируется только на новые findings, старый долг трекается отдельно. Запреты: игнорирование finding без suppression «потому что не уверен эксплуатируется ли» — молчание = долг. Раскрытие R-SEC-FIND-1..3 и R-SEC-FIND-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/security/java/findings-response/</guid>
<pubDate>Tue, 26 May 2026 07:54:04 GMT</pubDate>
</item>
<item>
<title>Где какая проверка — Gateway, BFF и Domain Service</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/where-the-check-goes/</link>
<description>Распределение auth-проверок по слоям: Gateway/API edge — аутентификация (валидация JWT, rate limiting). BFF/Application Layer — грубая авторизация по роли (RBAC): @PreAuthorize hasRole. Domain Service — авторизация по ресурсу (ABAC): order.customerId == jwt.sub. ABAC никогда на Gateway — Gateway не знает доменную модель. Каждый слой имеет свою responsibility — Gateway не делает RBAC, Domain не делает JWT validation. Раскрытие AUTH-1..AUTH-3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/where-the-check-goes/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>JWT validation — Spring Security oauth2ResourceServer и JWK Set cache</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/jwt-validation/</link>
<description>JWT validation в Spring: через oauth2ResourceServer().jwt() — кастомный фильтр запрещён (маскирует ошибки). JWK Set тянется из IdP по jwk-set-uri, кеш 5 минут default, вручную распаковывать запрещено. При невалидной подписи или просроченном exp — 401 Unauthorized (не 403). Семантика: 401 = не аутентифицирован, 403 = прав не хватает. Раскрытие AUTH-4..AUTH-6.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/jwt-validation/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>RBAC — маппинг ролей JWT и @PreAuthorize</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/rbac-roles/</link>
<description>RBAC в Spring: роли в JWT — realm_access.roles (Keycloak) или scope (OAuth2). На вход handler приходят как SimpleGrantedAuthority с префиксом ROLE_ через JwtAuthenticationConverter. Разрешённые роли UCP: customer, seller, admin, system — любая другая роль = пересмотр Bounded Context. На каждом REST-endpoint @PreAuthorize обязательна — endpoint без проверки = критическое нарушение. RBAC отвечает endpoint-level, не resource-level (для этого ABAC). Раскрытие AUTH-7..AUTH-9.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/rbac-roles/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>ABAC — владение ресурсом через @access-бин или handler-check</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/abac-resource-ownership/</link>
<description>ABAC в Spring: когда команда работает с агрегатом по id — обязателен ABAC. Два способа: @PreAuthorize @access.canEditOrder для простых случаев, либо проверка внутри Handler — загрузить агрегат, сравнить aggregate.ownerId с jwt.sub, FORBIDDEN. ABAC-логика выносится в @Component access бин или Handler — не размазывается по контроллерам. Для роли admin ABAC обходится (полный доступ), но каждое действие admin пишется в audit log. Раскрытие AUTH-10..AUTH-12.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/abac-resource-ownership/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>Service-to-service — mTLS и Client Credentials Flow</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/service-to-service/</link>
<description>Service-to-service auth: mTLS (рекомендуется) через двусторонний TLS на K8s Service Mesh / Istio, либо Client Credentials Flow (grant_type=client_credentials) с scope=service:operation. Внутренние клиенты в adapter-out-* никогда не делают RestTemplate без mTLS или Bearer — анонимный inter-service трафик = критическое нарушение. mTLS даёт автоматическую identity-привязку (CN сертификата = service-account). Раскрытие AUTH-13..AUTH-14.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/service-to-service/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>Audit admin-команд — *_audit_log таблица и @Around-аспект</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/audit-admin/</link>
<description>Audit admin-команд: каждая команда от роли admin изменяющая state агрегата обязана писать строку в *_audit_log таблицу с полями actor_id, occurred_at, action, resource_type, resource_id, metadata JSONB. Реализация — @Around-аспект или явный вызов в Handler-е. Та же БД, одна транзакция. Append-only: только INSERT, REVOKE UPDATE/DELETE. При admin override ABAC audit обязателен — compliance, расследование инцидентов. Раскрытие AUTH-15.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/audit-admin/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>PII и секреты — что нельзя в логи, detail и Kafka</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/pii-and-secrets/</link>
<description>PII-поля (email, phone, ФИО, адрес, паспорт) не попадают: в логи (даже DEBUG), в Exception.getMessage и далее в ProblemDetails.detail, в Kafka-события (передавать только id, payload подгружается потребителем). Секреты (client-secret, JDBC-пароли, ключи шлюзов) никогда не коммитятся в git — только через Vault / SealedSecrets / env vars. RestControllerAdvice не выводит cause.getMessage() в detail — только заранее заданное сообщение по коду. Раскрытие AUTH-16..AUTH-18.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/pii-and-secrets/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>Идемпотентность как часть auth-контракта — Idempotency-Key для money</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/idempotency/</link>
<description>Идемпотентность как часть auth-контракта: любая команда меняющая деньги или резерв (CreateOrder, ConfirmPayment, Refund) обязана требовать Idempotency-Key header. Повторный вызов с тем же ключом возвращает прежний результат не дубль. Защита от retry клиента, мобильного приложения, S2S, network timeout. Без Idempotency-Key два списания одного клиента = money-инцидент. Тот же ключ + другая команда = 409 Conflict. Раскрытие AUTH-19.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/idempotency/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>Хранение токенов на клиенте — HttpOnly cookie и refresh rotation</title>
<link>https://vikulin-va.ru/standards/backend/auth-patterns/java/client-token-storage/</link>
<description>Хранение токенов SPA: HttpOnly + Secure + SameSite=Lax cookie. localStorage запрещён — уязвим к XSS, любой скрипт читает. Refresh-токены с rotation: при каждом обновлении старый инвалидируется; при повторном использовании старого RT — компрометация, инвалидируется вся цепочка. SameSite=Lax защищает от CSRF на cross-site GET; Secure требует HTTPS. BFF pattern — server-side хранит токены. Раскрытие AUTH-20..AUTH-21.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/auth-patterns/java/client-token-storage/</guid>
<pubDate>Tue, 26 May 2026 07:33:54 GMT</pubDate>
</item>
<item>
<title>Где какая защита — outbound, internal, scheduler, inbound</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/where-protection-goes/</link>
<description>Где применять Resilience4j в Spring Boot-сервисе и где не нужно: outbound HTTP — полный набор (timeout + CB + Bulkhead + опционально Retry); internal service-to-service — timeout + CB; schedulers / outbox-relay — task-queue retry (DB-driven), не Resilience4j; inbound REST — RateLimiter на API Gateway. Запреты: Resilience4j вокруг локальных операций (репозиторий, JOOQ, in-memory). Раскрытие правил R-RES-WHERE-1..4 и R-RES-WHERE-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/where-protection-goes/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Per-system isolation — отдельный OkHttpClient и CB на каждую внешнюю систему</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/per-system-isolation/</link>
<description>Per-system isolation в Resilience4j: на каждую внешнюю систему отдельный OkHttpClient с собственным ConnectionPool, Dispatcher, CircuitBreaker и Bulkhead. Имя bean'а и инстансов R4J совпадают (sber, odnakassa, insurance). Connection pool sizing: pool = maxConcurrent × 1.2; total всех систем ≤ HikariCP size / 2. Запреты: shared OkHttpClient на несколько систем, дефолтный Builder() без явного pool/dispatcher. Раскрытие правил R-RES-ISO-1..3 и R-RES-ISO-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/per-system-isolation/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Timeouts — connectTimeout &lt; readTimeout &lt; callTimeout без бесконечностей</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/timeouts/</link>
<description>Иерархия timeouts в OkHttpClient: connectTimeout (TCP/TLS handshake, 2-5s) &lt; readTimeout (между байтами ответа, 10-60s) &lt; callTimeout (общий cap, ≥ connect+read+1s buffer). Per-system конфиг через &lt;system&gt;ClientSettings (@ConfigurationProperties). При traceparent с TimeBudget — клиент уважает оставшийся бюджет. Запреты: OkHttpClient без timeouts (default ∞), callTimeout &lt; readTimeout, readTimeout &gt;60s для sync-вызова. Раскрытие правил R-RES-TO-1..3 и R-RES-TO-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/timeouts/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Circuit Breaker — fast-fail при отказе внешней системы</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/circuit-breaker/</link>
<description>Circuit Breaker в Resilience4j: @CircuitBreaker(name = sber) на public-методе out-adapter (не на generated client, не на handler-е, не на репозитории). Sliding window COUNT_BASED size 50, minimumNumberOfCalls 10, failureRateThreshold 50% (30% для критичных), waitDurationInOpenState 30s, slowCallDurationThreshold = readTimeout/2. CallNotPermittedException маппится в port-specific exception. Запреты: CB на репозитории, custom CB на try/catch + AtomicInteger, общий name default для разных систем. Раскрытие правил R-RES-CB-1..6 и R-RES-CB-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/circuit-breaker/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Retry — только при идемпотентности (read или Idempotency-Key)</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/retry/</link>
<description>Когда применять @Retry в Resilience4j: только если метод — read (GET-эквивалент) или write с Idempotency-Key (внешняя система дедуплицирует). max-attempts: 3 типовое, 5 предел; больше — task-queue. enable-exponential-backoff: true с multiplier 2.0. retry-exceptions: IOException, HttpServerErrorException; 4xx игнорируем. In-memory retry для транзиентов &lt;5s; task-queue для отказов &gt;30s. Запреты: @Retry на write без Idempotency-Key (двойное списание), @Retry на 4xx, без exp backoff, Spring Retry для outbound. Раскрытие правил R-RES-RE-1..5 и R-RES-RE-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/retry/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Bulkhead — semaphore-based лимит на concurrent calls</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/bulkhead/</link>
<description>Bulkhead в Resilience4j: @Bulkhead(name = sber) обязательный слой отдельно от connection pool — pool ограничивает TCP, bulkhead ограничивает Java concurrent calls. Тип SEMAPHORE (не THREADPOOL — теряет MDC/SecurityContext). Sizing: maxConcurrentCalls = pool maxConcurrent × 0.8 (запас 20% — bulkhead срабатывает раньше pool). maxWaitDuration 100ms короткое, иначе теряется fail-fast. Запреты: thread-pool bulkhead для outbound (MDC/SecurityContext теряются без DelegatingSecurityContextExecutor). Раскрытие правил R-RES-BH-1..3 и R-RES-BH-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/bulkhead/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Fallback — три легитимных случая (cached read, default value, async-mode write)</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/fallback/</link>
<description>Когда fallback допустим в Resilience4j: cached read (отдать данные из локального кеша / последнего успешного ответа), default value для read (пустой список, нейтральный объект), async-mode для write (202 Accepted + task-queue). Контракт fallback-метода: same return type, дополнительный last-параметр Throwable. Запреты: fallback с null/Money.ZERO для money-операций, тихий fallback с success (клиент не узнает о проблеме), каскадный fallback в другой провайдер без своего CB. Раскрытие правил R-RES-FB-1..2 и R-RES-FB-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/fallback/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Конфигурация Resilience4j — declarative через application.yml</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/configuration/</link>
<description>Конфиг Resilience4j через application.yml (declarative), не через @Bean CustomCircuitBreakerConfig. Defaults в секции default, переопределения per-instance через base-config: default. Имена instances совпадают с именами beans и систем (sber, odnakassa, insurance). Это позволяет менять параметры через Spring Cloud Config / Vault без redeploy. Запреты: программная конфигурация через CircuitBreakerConfig.custom() без причины (скрыта от Cloud Config). Раскрытие правил R-RES-CFG-1..3 и R-RES-CFG-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/configuration/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Связка с OpenAPI generator — аннотации на out-adapter, не на generated client</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/openapi-generator-binding/</link>
<description>Где вешать Resilience4j-аннотации при использовании openapi-generator: на public-методе out-adapter класса, оборачивающего generated client. Не на generated interface (перегенерируется), не в executeCall&lt;T&gt; helper (теряется compile-time check имени), не на handler. Target generator для нового кода — spring-restclient (Spring 6.1+) с native RestClient, Observation API, OTel auto-config. OpenAPI-спека внешнего API в &lt;system&gt;-client-generator. Между generated DTO и port-интерфейсом обязателен mapper (Plain Java или MapStruct). Запреты: аннотации на generated &lt;X&gt;Api interface, @CircuitBreaker в executeCall с backendName-строкой, возврат generated DTO из port-метода. Раскрытие правил R-RES-OAS-1..4 и R-RES-OAS-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/openapi-generator-binding/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Health checks — HealthIndicator с TTL-кешем, light probe, не business-операция</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/health-checks/</link>
<description>HealthIndicator в Spring Boot Actuator на каждую внешнюю систему: SberHealthIndicator implements HealthIndicator. Probe cached с TTL 30s — не каждый actuator-call ходит в Sber. Probe-метод — light GET /health или OPTIONS /, не реальный business-вызов. Health отражается в /actuator/health/&lt;system&gt;, k8s readinessProbe смотрит на /actuator/health/readiness. Запреты: sync-probe без кеша (DDoS внешней системы силами k8s probes каждые 5s), health-probe с business-операцией (изменение состояния, test-данные в проде). Раскрытие правил R-RES-HC-1..4 и R-RES-HC-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/health-checks/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Async и polling — task-queue вместо Thread.sleep в sync-handler</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/async-and-polling/</link>
<description>Async polling в Resilience4j: если внешняя система требует polling, реализуется через task-queue (БД с next_attempt_at), не через Thread.sleep в синхронном handler-е. Команда создаёт &lt;X&gt;PollingTask в БД, возвращает 202 Accepted клиенту, scheduler (@Scheduled каждые 5s) дёргает внешнюю систему. Thread.sleep в sync-методе допустим только при total wait &lt;2s. Для CompletableFuture-возврата — @TimeLimiter(name = &lt;system&gt;) обязателен. Запреты: Thread.sleep(N) в цикле в синхронном handler-е (блокирует worker), любая Thread.sleep &gt; 5s. Раскрытие правил R-RES-ASYNC-1..3 и R-RES-ASYNC-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/async-and-polling/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Observability Resilience4j — Micrometer-метрики, OTel-spans, structured logs</title>
<link>https://vikulin-va.ru/standards/backend/resilience/java/observability/</link>
<description>Observability для Resilience4j: Micrometer метрики через resilience4j-micrometer dependency (resilience4j_circuitbreaker_state, resilience4j_circuitbreaker_calls, resilience4j_retry_calls, resilience4j_bulkhead_available_concurrent_calls). OTel-spans на adapter-методах с атрибутами circuit_breaker.state и external.system. Логирование structured, при state-transition CB — WARN с system, prev_state, new_state, failure_rate (не на каждый успешный call). Запреты: отключение metrics через management.metrics.enable.resilience4j=false без причины — без них SRE не увидит «у нас CB Sber стабильно half-open» до прода. Раскрытие правил R-RES-OBS-1..3 и R-RES-OBS-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/resilience/java/observability/</guid>
<pubDate>Mon, 25 May 2026 19:09:38 GMT</pubDate>
</item>
<item>
<title>Где валидировать в Spring Boot — три места и ни одно из них не Handler</title>
<link>https://vikulin-va.ru/standards/backend/validation/java/where-to-validate/</link>
<description>Три места валидации в Spring Boot UCP-сервисе: @Valid на контроллере для входного HTTP DTO, @Validated на @ConfigurationProperties для конфига, бросание domain exception в методе агрегата для доменных инвариантов. Запреты: manual if-проверки в Handler, дублирование Jakarta на UseCase command, @ConfigurationProperties без @Validated, доменный инвариант через @Min на поле Aggregate. Раскрытие правил R-VLD-WHERE-1..4 и R-VLD-WHERE-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/validation/java/where-to-validate/</guid>
<pubDate>Mon, 25 May 2026 17:57:13 GMT</pubDate>
</item>
<item>
<title>Стандартные constraints Jakarta Validation — @NotNull, @Size, @Email, @Pattern</title>
<link>https://vikulin-va.ru/standards/backend/validation/java/standard-constraints/</link>
<description>Какие стандартные constraints из Jakarta Validation использовать в Spring Boot: @NotNull/@NotBlank/@NotEmpty по типу, @Size/@Min/@Max/@DecimalMin для размеров, @Email вместо ручного regex, @Pattern только для редких форматов, @Past/@Future для времени, тип-зависимая валидация (Long vs long). Запреты: @NotNull на примитиве (молчит), кастомный regex для email, composite-аннотации поверх стандартных. Раскрытие правил R-VLD-STD-1..5 и R-VLD-STD-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/validation/java/standard-constraints/</guid>
<pubDate>Mon, 25 May 2026 17:57:13 GMT</pubDate>
</item>
<item>
<title>Custom constraints в Jakarta Validation — annotation + ConstraintValidator пара</title>
<link>https://vikulin-va.ru/standards/backend/validation/java/custom-constraints/</link>
<description>Когда писать custom constraint в Spring Boot: для частых доменных форматов (RussianPhone, VatNumber, BicCode), которые встречаются на 3+ полях. Пара annotation interface + ConstraintValidator. isValid(null) возвращает true (комбинируется с @NotNull). Stateless validator без runtime-state. Расположение: core/&lt;bc&gt;/validation для доменных, common/validation для общих технических. Имена без префиксов Valid/Check/Is. Запреты: isValid(null)=false, constraint в одном файле с DTO, inline @AssertTrue. Раскрытие правил R-VLD-CC-1..5 и R-VLD-CC-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/validation/java/custom-constraints/</guid>
<pubDate>Mon, 25 May 2026 17:57:13 GMT</pubDate>
</item>
<item>
<title>Validation groups в Spring Boot — один DTO с разными required в разных контекстах</title>
<link>https://vikulin-va.ru/standards/backend/validation/java/validation-groups/</link>
<description>Что такое validation groups в Jakarta Validation: один DTO с разными required-полями в разных сценариях (OnCreate vs OnUpdate). Group — пустой маркер-interface. @Validated(OnCreate.class) на контроллере. Когда применять — только когда тот же класс DTO реально нужен в разных контекстах. Запреты: группы для строгая/мягкая (это два разных DTO), цепочки @Validated({A.class, B.class, C.class}) — класс делает слишком много. Раскрытие правил R-VLD-GRP-1..2 и R-VLD-GRP-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/validation/java/validation-groups/</guid>
<pubDate>Mon, 25 May 2026 17:57:13 GMT</pubDate>
</item>
<item>
<title>Cross-field validation в Jakarta — class-level constraint, не @AssertTrue в DTO</title>
<link>https://vikulin-va.ru/standards/backend/validation/java/cross-field-validation/</link>
<description>Как валидировать правила между несколькими полями DTO в Spring Boot: class-level @Constraint аннотация на классе DTO + ConstraintValidator на сам класс. Пример — @DateRange (dateFrom ≤ dateTo). Прицеп ошибки к конкретному полю через addPropertyNode. Имя описывает правило (@DateRange, @PasswordsMatch), не объект (@OrderRequestValid). Запреты: @AssertTrue-метод в DTO (не переиспользуется), cross-field валидация в Handler перед dispatcher.dispatch (это контракт, не бизнес). Раскрытие правил R-VLD-XF-1..2 и R-VLD-XF-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/validation/java/cross-field-validation/</guid>
<pubDate>Mon, 25 May 2026 17:57:13 GMT</pubDate>
</item>
<item>
<title>OpenAPI-сгенерированные DTO в Spring Boot — useBeanValidation и правила в YAML</title>
<link>https://vikulin-va.ru/standards/backend/validation/java/openapi-generated-dto/</link>
<description>Как валидируются generated DTO из OpenAPI в Spring Boot: useBeanValidation=true в openapi-generator config (без него generated DTO без аннотаций, @Valid silent-passes), все validation-правила в OpenAPI YAML (один источник правды), маппинг keyword → Jakarta annotation (minLength → @Size, format: email → @Email, $ref → @Valid). Custom constraint через wrapper-class в коде. Запреты: дописывать аннотации в build/generated, дублировать в YAML и в Java, handcrafted DTO без OpenAPI. Раскрытие правил R-VLD-OAS-1..6 и R-VLD-OAS-X1..X5.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/validation/java/openapi-generated-dto/</guid>
<pubDate>Mon, 25 May 2026 17:57:13 GMT</pubDate>
</item>
<item>
<title>Валидация конфигурации в Spring Boot — @ConfigurationProperties с @Validated и fail-fast</title>
<link>https://vikulin-va.ru/standards/backend/validation/java/configuration-validation/</link>
<description>Как валидировать конфиг в Spring Boot: @ConfigurationProperties + @Validated на классе → невалидный конфиг падает на старте с BeanCreationException, не на первом запросе. @NotBlank для String, @NotNull для object, @Min/@Max для числовых лимитов, @Valid для nested-структур, @DurationMax для бизнес-пределов. Запреты: @ConfigurationProperties без @Validated, @Value для required-конфига (не валидируется). Раскрытие правил R-VLD-CFG-1..4 и R-VLD-CFG-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/validation/java/configuration-validation/</guid>
<pubDate>Mon, 25 May 2026 17:57:13 GMT</pubDate>
</item>
<item>
<title>Сообщения валидации и i18n — на русском, для пользователя, через {placeholders}</title>
<link>https://vikulin-va.ru/standards/backend/validation/java/messages-and-i18n/</link>
<description>Как писать message в Jakarta-аннотациях в Spring Boot: на русском (для пользователя на UI), без технических терминов, интерполяция через {value}/{min}/{max} из спецификации, локализация через {key} + messages_ru.properties для multi-language. Запреты: английский в message, технические термины (field, must be positive), дублирование message в каждом DTO для одного constraint. Раскрытие правил R-VLD-MSG-1..3 и R-VLD-MSG-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/validation/java/messages-and-i18n/</guid>
<pubDate>Mon, 25 May 2026 17:57:13 GMT</pubDate>
</item>
<item>
<title>Где кешируем — read-heavy данные, money с осторожностью, агрегаты никогда</title>
<link>https://vikulin-va.ru/standards/backend/caching/java/where-to-cache/</link>
<description>Что кешируем в Spring-сервисах: read-heavy и редко меняющиеся данные — справочники (часы), user profile (15-30 мин), feature flags (60 сек), heavy aggregations. Money-данные допустимы, но с TTL ≤ 30 секунд и явной @CacheEvict на каждом write. Cache-aside — дефолтный паттерн. Запреты: @Cacheable на write-методах (createOrder, confirmPayment); кеширование доменного агрегата целиком (нарушает границы, кешируем read-проекции OrderSummary); money без TTL/invalidation; результаты валидации и авторизации. Раскрытие правил R-CACHE-WHERE-1..3 и R-CACHE-WHERE-X1..X5.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/caching/java/where-to-cache/</guid>
<pubDate>Tue, 26 May 2026 04:47:10 GMT</pubDate>
</item>
<item>
<title>Конфигурация Spring Cache — RedisCacheManager и JSON-сериализация</title>
<link>https://vikulin-va.ru/standards/backend/caching/java/configuration/</link>
<description>Конфигурация Spring Cache: RedisCacheManager через spring-boot-starter-data-redis, не in-memory ConcurrentMapCacheManager (каждый pod имел бы свой кеш). Сериализация JSON через GenericJackson2JsonRedisSerializer, никогда Java native JdkSerializationRedisSerializer (deserialization vulnerability). Per-cache configuration с explicit TTL. @ConfigurationProperties + @Validated для cache settings. В тестах — ConcurrentMapCacheManager или Testcontainers, не моки Cache. Запреты: JdkSerializationRedisSerializer, ConcurrentMapCacheManager в multi-instance проде, один глобальный TTL, @EnableCaching без CacheManager-бина (silent NoOpCacheManager). Раскрытие правил R-CACHE-CFG-1..5 и R-CACHE-CFG-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/caching/java/configuration/</guid>
<pubDate>Tue, 26 May 2026 04:47:10 GMT</pubDate>
</item>
<item>
<title>Ключи кеша — namespace, SpEL и custom KeyGenerator</title>
<link>https://vikulin-va.ru/standards/backend/caching/java/keys/</link>
<description>Ключи Spring Cache: namespace через cacheNames (Redis user-profiles::42), kebab-case slug для имени кеша. Ключ через SpEL explicit: key = "#userId", composite через #customerId + ":" + #status. Custom KeyGenerator — только для очень сложных ключей. Запреты: дефолтный generator на multi-arg (SimpleKey ломается); Object.toString() в ключе для DTO без переопределения; один общий cache "shared-cache" (теряется namespacing); plain PII/токенов в ключе — хешировать через SHA-256. Раскрытие правил R-CACHE-KEY-1..4 и R-CACHE-KEY-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/caching/java/keys/</guid>
<pubDate>Tue, 26 May 2026 04:47:10 GMT</pubDate>
</item>
<item>
<title>TTL — explicit duration per cache и типовые значения по характеру данных</title>
<link>https://vikulin-va.ru/standards/backend/caching/java/ttl/</link>
<description>TTL Spring Cache: каждый именованный cache имеет explicit duration, никаких infinite-кешей. Типовые значения: static reference — часы; user profile — 15-30 мин; feature flags — 30-60 сек; heavy aggregations — 5-10 мин; money — 5-30 сек. TTL через application.yml, не hard-coded — SRE меняет под нагрузку без redeploy. Если cached data имеет естественный invalidation event — TTL longer, invalidation does heavy lifting. Запреты: TTL = Duration.ZERO или infinite (Redis при max-memory eviction по LRU без вашего контроля); TTL &gt; 24 часов (deploy чаще, кеш переживает релиз со старой структурой DTO); money без TTL. Раскрытие правил R-CACHE-TTL-1..4 и R-CACHE-TTL-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/caching/java/ttl/</guid>
<pubDate>Tue, 26 May 2026 04:47:10 GMT</pubDate>
</item>
<item>
<title>Invalidation — @CacheEvict, @EventListener и distributed-sync</title>
<link>https://vikulin-va.ru/standards/backend/caching/java/invalidation/</link>
<description>Invalidation Spring Cache: на каждом write-методе того же агрегата — @CacheEvict с явным key; @Caching композит для нескольких кешей. При доменных событиях (UserUpdatedEvent) — invalidation через @EventListener + @CacheEvict (пустой метод-marker). Distributed cache invalidation — встроенно в Redis backend. Запреты: @CacheEvict(allEntries=true) без причины (холодный старт = нагрузка на БД спайком); полагаться только на TTL для money/orders consistency; eventual consistency без декларации в OpenAPI description. Раскрытие правил R-CACHE-INV-1..4 и R-CACHE-INV-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/caching/java/invalidation/</guid>
<pubDate>Tue, 26 May 2026 04:47:10 GMT</pubDate>
</item>
<item>
<title>Паттерны кеширования — cache-aside, write-through и refresh-ahead</title>
<link>https://vikulin-va.ru/standards/backend/caching/java/patterns/</link>
<description>Паттерны Spring Cache: cache-aside (lazy load + write evict) — дефолтный, простой и читаемый. Write-through через @CachePut — для высокочастотных read+write одного значения, на write кеш обновляется явно не evict-ится. Refresh-ahead через @Scheduled — для критичных hot keys (top-100 продуктов), гарантирует no cache miss for hot keys. Запреты: write-behind (write в кеш, async в БД) для money/critical — crash до flush = потеря данных; mix паттернов на одном cache (cache-aside + write-through одновременно) — invalidation logic становится непонятной. Раскрытие правил R-CACHE-PATTERN-1..3 и R-CACHE-PATTERN-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/caching/java/patterns/</guid>
<pubDate>Tue, 26 May 2026 04:47:10 GMT</pubDate>
</item>
<item>
<title>Cache stampede — distributed lock и refresh-ahead против thundering herd</title>
<link>https://vikulin-va.ru/standards/backend/caching/java/cache-stampede/</link>
<description>Cache stampede — multiple parallel requests на холодную ключ: все промахиваются → N одновременных запросов в БД → инцидент. Для локального кеша — @Cacheable(sync=true), блокирует параллельные вызовы. Для distributed cache (Redis) sync=true не помогает (lock только within JVM): distributed lock через Redis SET NX EX или Redisson RLock с double-check; probabilistic refresh. Для hot keys — refresh-ahead через @Scheduled, stampede исключён по дизайну. Запреты: игнорировать stampede для hot endpoints (&gt;100 RPS); synchronized-блок Java для distributed-cache защиты. Раскрытие правил R-CACHE-STAMP-1..3 и R-CACHE-STAMP-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/caching/java/cache-stampede/</guid>
<pubDate>Tue, 26 May 2026 04:47:10 GMT</pubDate>
</item>
<item>
<title>Observability кеша — hit rate, eviction metrics и Redis-side мониторинг</title>
<link>https://vikulin-va.ru/standards/backend/caching/java/observability/</link>
<description>Observability Spring Cache: автоматический экспорт через Micrometer — cache_gets_total{cache,result=hit|miss}, cache_puts_total, cache_evictions_total, cache_size. Cache hit rate — основная метрика здоровья: hits / (hits + misses); алерт при hit rate &lt; 70% для долго существующих кешей. Eviction логировать на DEBUG. Redis-side метрики через отдельный Redis Exporter — redis_memory_used_bytes, redis_keys_total. Запреты: отключение Spring Cache metrics (management.metrics.enable.cache=false) — без них SRE не увидит что кеш бесполезен. Раскрытие правил R-CACHE-OBS-1..4 и R-CACHE-OBS-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/caching/java/observability/</guid>
<pubDate>Tue, 26 May 2026 04:47:10 GMT</pubDate>
</item>
<item>
<title>Kafka Producer — idempotence, acks=all, partition key</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/producer/</link>
<description>Kafka producer в Spring: enable.idempotence=true всегда — автоматически acks=all, retries=MAX, max.in.flight ≤ 5, exactly-once на partition. Partition key обязателен для бизнес-событий — без ключа round-robin теряет ordering; дефолтный ключ — aggregate id. JSON сериализация по умолчанию. KafkaTemplate.send из use-case handler-а запрещён для domain-событий — через outbox. Запреты: enable.idempotence=false (дубликаты при retry); acks=0/1 (потеря данных при rebalance/failure leader); send без partition key; send в @Transactional с DB (Kafka не XA). Раскрытие R-KFK-PROD-1..4 и R-KFK-PROD-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/producer/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Kafka Consumer — manual ack, group.id, concurrency и max.poll.interval</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/consumer/</link>
<description>Kafka consumer в Spring: уникальный group.id формата &lt;service&gt;-&lt;purpose&gt;. Manual ack (ack-mode=MANUAL_IMMEDIATE), auto-commit опасен — offset коммитится по таймеру, crash = потеря. Listener idempotent — at-least-once норма. auto.offset.reset=earliest для critical. Concurrency ≤ partitions. max.poll.interval ≥ времени обработки batch. Запреты: enable.auto.commit=true (crash = loss); Thread.sleep &gt; 1s (rebalance); group.id отсутствует/общий; HTTP без CB/Bulkhead (зависает, rebalance, дубликаты). Раскрытие R-KFK-CONS-1..6 и R-KFK-CONS-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/consumer/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Outbox publishing — атомарная публикация Kafka-событий из write-handler</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/outbox-publishing/</link>
<description>Outbox publishing в Kafka: запись в outbox_event в той же DB-транзакции что бизнес-write, либо обе commit либо обе rollback. Outbox-relay — отдельный @Component с @Scheduled, читает unpublished с FOR UPDATE SKIP LOCKED, публикует, помечает published_at. Topic name &lt;service&gt;.&lt;aggregate&gt;.&lt;event&gt;. Relay в batch 10-50. Запреты: KafkaTemplate.send в @Transactional с DB; @TransactionalEventListener для Kafka (потеря при crash между commit и publish); outbox без partial-индекса WHERE published_at IS NULL (full scan тормоза). Раскрытие R-KFK-OBX-1..4 и R-KFK-OBX-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/outbox-publishing/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Idempotent consumer — processed_event таблица и dedup по eventId</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/idempotent-consumer/</link>
<description>Idempotent consumer в Kafka: at-least-once = дубликаты норма. Каждое событие имеет eventId UUID v7 в payload, consumer проверяет через processed_event таблицу с PRIMARY KEY на event_id. Запись в processed_event и бизнес-результат в одной транзакции. Money — двойная защита: eventId + Idempotency-Key на downstream HTTP. TTL через partitioning или background-job. Запреты: listener без проверки eventId для critical; Kafka offset как dedup-ключ (offset зависит от consumer-group). Раскрытие R-KFK-IDEM-1..4 и R-KFK-IDEM-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/idempotent-consumer/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Retry topic + DLQ — non-blocking retry с возрастающим backoff</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/retry-and-dlq/</link>
<description>Retry topic + DLQ в Kafka: blocking-retry в listener (Thread.sleep + retry в цикле) — антипаттерн, блокирует poll-цикл. Non-blocking retry через отдельные топики *.retry-1m, *.retry-10m, *.dlq. @RetryableTopic с attempts=4, backoff multiplier=10. Retry только для transient (сеть, 5xx, DB timeout); не retry для 4xx, validation, NPE. DLQ-monitoring обязателен. Replay из DLQ — manual. Запреты: blocking retry через Thread.sleep; try/catch + log.error + ack (событие потеряно); retry без max-attempts; DLQ без monitoring. Раскрытие R-KFK-RTRY-1..4 и R-KFK-RTRY-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/retry-and-dlq/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Event design — past tense, eventId UUID v7 и forward-compatible schema</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/event-design/</link>
<description>Дизайн Kafka events: имя в прошедшем времени (OrderConfirmed, не ConfirmOrder). Payload: eventId UUID v7, eventType версионированный (order.confirmed.v1), occurredAt (когда произошло, не когда опубликовано), aggregateType+aggregateId, бизнес-данные. PII не в payload широковещательных topics. Forward-compatible: добавление non-breaking; удаление/переименование — новый eventType.v2. Domain event — Java record в core/&lt;bc&gt;/domain/event/. Запреты: имя — команда (ConfirmOrder вместо OrderConfirmed); aggregate целиком в payload; PII в широких topics; breaking change без версии. Раскрытие R-KFK-EVT-1..4 и R-KFK-EVT-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/event-design/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Конфигурация Kafka — application.yml, trusted-packages и missing-topics-fatal</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/configuration/</link>
<description>Конфигурация Kafka в Spring Boot через @ConfigurationProperties + @Validated. application.yml: bootstrap-servers через env, producer enable.idempotence=true acks=all, consumer auto-offset-reset=earliest enable-auto-commit=false, listener ack-mode=MANUAL_IMMEDIATE missing-topics-fatal=true. spring.json.trusted.packages — explicit allow-list (security). missing-topics-fatal=true в проде — fail-fast если топика нет. Запреты: spring.json.trusted.packages="*" — RCE через deserialization gadgets; bootstrap-servers hard-coded без env-substitution. Раскрытие R-KFK-CFG-1..4 и R-KFK-CFG-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/configuration/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Observability Kafka — consumer lag alerts, traceparent и DLQ-size</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/observability/</link>
<description>Observability Kafka в Spring: автоматический Micrometer экспорт — kafka_consumer_lag (главный сигнал), kafka_producer_record_error_total, kafka_consumer_records_consumed_total. Alert на consumer lag &gt; N для критичных topics; threshold per criticality (money 100, orders 1000, analytics 100000). Traceparent в Kafka headers — distributed trace продолжается через producer/consumer, Spring Kafka + OTel автоконфиг. DLQ-size alert обязателен. Запреты: отсутствие consumer-lag alerts — пропадание сообщений замечается через жалобы клиентов. Раскрытие R-KFK-OBS-1..4 и R-KFK-OBS-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/observability/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Kafka Security — TLS, ACLs per-сервис и restricted PII topics</title>
<link>https://vikulin-va.ru/standards/backend/kafka/java/security/</link>
<description>Безопасность Kafka в проде: TLS (security.protocol=SSL) обязателен для cross-network; SASL/PLAIN over plaintext запрещён. ACLs per-сервис — каждый service-account на свои топики, blast-radius containment. PII — отдельные restricted topics с узким ACL, либо слабая ссылка: customerId в широком topic, PII подгружается через customer-service. Запреты: PLAINTEXT в проде (только локальная разработка); один service-account на весь кластер (нет blast-radius containment, компрометация одного сервиса = доступ ко всем топикам). Раскрытие R-KFK-SEC-1..3 и R-KFK-SEC-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/kafka/java/security/</guid>
<pubDate>Tue, 26 May 2026 07:14:19 GMT</pubDate>
</item>
<item>
<title>Logging — structured JSON, MDC, уровни и PII-гигиена</title>
<link>https://vikulin-va.ru/standards/backend/observability/java/logging/</link>
<description>Логирование в Java/Spring: structured JSON в проде через logstash-logback-encoder, текстовый pattern только в dev; @Slf4j через Lombok с {} placeholders; уровни ERROR/WARN/INFO/DEBUG/TRACE; MDC поля traceId, requestId, userId автоматически в JSON; логи на границах. Запреты: PII в логах (email, phone, паспорт, токены) — критическое нарушение; System.out.println; string-concat в log args; log.error без stack trace; полный request body для money; INFO на каждый HTTP-запрос. Раскрытие правил R-OBS-LOG-1..6 и R-OBS-LOG-X1..X6.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/observability/java/logging/</guid>
<pubDate>Mon, 25 May 2026 19:35:58 GMT</pubDate>
</item>
<item>
<title>Metrics — Micrometer, Prometheus, RED/USE и стандартные dimensions</title>
<link>https://vikulin-va.ru/standards/backend/observability/java/metrics/</link>
<description>Метрики в Spring Boot: Micrometer + Prometheus через spring-boot-starter-actuator, endpoint /actuator/prometheus. Стандартизованные dimensions service/env/version через management.metrics.tags.*. RED method для HTTP (http_server_requests_seconds — rate, errors, duration p95), USE для resources (jvm_memory, executor pools, hikaricp_connections). Custom business metrics через MeterRegistry: Counter, Gauge, Timer, DistributionSummary. Имена snake_case с единицей. Tags — низкая cardinality. Запреты: user_id/request_id как tag value (OOM в Prometheus), не-стандартизованные dimensions, micrometer-core без registry, /actuator/prometheus публично. Раскрытие правил R-OBS-MTR-1..7 и R-OBS-MTR-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/observability/java/metrics/</guid>
<pubDate>Mon, 25 May 2026 19:35:58 GMT</pubDate>
</item>
<item>
<title>Tracing — OpenTelemetry, traceparent, sampling и span attributes</title>
<link>https://vikulin-va.ru/standards/backend/observability/java/tracing/</link>
<description>Distributed tracing в Spring Boot через OpenTelemetry автоинструментацию: opentelemetry-spring-boot-starter даёт auto-spans для HTTP server/client, JDBC, Kafka, Spring Cache. Traceparent W3C propagation между сервисами автоматически. Manual spans для use case handlers через Tracer и try-with-resources. Span attributes — business context (orderId, paymentMethod), не PII. Sampling 1-10% + 100% для error-traces через tail-based. TraceId/spanId в MDC автоматически через OpenTelemetryAppender — связка лог-запись с trace. Запреты: sampling 100% в проде, PII в attributes, manual span без try-finally, trace разрывается на @Async. Раскрытие правил R-OBS-TRC-1..6 и R-OBS-TRC-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/observability/java/tracing/</guid>
<pubDate>Mon, 25 May 2026 19:35:58 GMT</pubDate>
</item>
<item>
<title>Health checks — liveness, readiness, custom HealthIndicator и /actuator/info</title>
<link>https://vikulin-va.ru/standards/backend/observability/java/health-checks/</link>
<description>Health checks через Spring Boot Actuator с разделением liveness и readiness. /actuator/health/liveness — UP пока процесс отвечает, не зависит от внешних систем. /actuator/health/readiness — UP когда сервис готов принимать трафик. Custom HealthIndicator для критичной внешней системы с TTL-кешем. /actuator/info содержит git.commit.id, build.version. Запреты: business-state в health check (orderCount &gt; N → DOWN), liveness зависит от внешних систем (loop при недоступности), health-probe делает business-операцию (ddos самих себя). Раскрытие правил R-OBS-HC-1..3 и R-OBS-HC-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/observability/java/health-checks/</guid>
<pubDate>Mon, 25 May 2026 19:35:58 GMT</pubDate>
</item>
<item>
<title>Конфигурация observability — management port, exposure, Logback profiles</title>
<link>https://vikulin-va.ru/standards/backend/observability/java/configuration/</link>
<description>Конфигурация observability в Spring Boot: отдельный management port (server.port 8080 + management.server.port 8081) для изоляции actuator от business traffic и сетевой защиты. Explicit exposure список — только health/info/metrics/prometheus. Default percentiles-histogram для http.server.requests + SLO buckets. Стандартные tags через management.metrics.tags. Logback-spring.xml с двумя springProfile — dev/test (text pattern) и prod/staging (LogstashEncoder с MDC keys). Запреты: exposing /actuator/env, /heapdump, /threaddump публично; один port для business + actuator в проде; exposure.include "*". Раскрытие правил R-OBS-CFG-1..4 и R-OBS-CFG-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/observability/java/configuration/</guid>
<pubDate>Mon, 25 May 2026 19:35:58 GMT</pubDate>
</item>
<item>
<title>Context propagation (MDC) — filter, TaskDecorator и MDC.clear() в finally</title>
<link>https://vikulin-va.ru/standards/backend/observability/java/context-propagation/</link>
<description>Context propagation через MDC в Spring Boot: MdcFilter с @Order(HIGHEST_PRECEDENCE) populates requestId из X-Request-Id header на каждый incoming HTTP request, MDC.clear() в finally обязательно. TraceId/spanId автоматически через OpenTelemetry Logback appender. UserId populates после JWT-валидации в Security filter chain. Async/CompletableFuture — пропагация через TaskDecorator с copyOfContextMap → setContextMap → clear. Запреты: MDC без MDC.clear() в finally — утечка контекста между requests в thread pool, чужой userId в логах = compliance incident; MDC.put в произвольных местах; @Async без TaskDecorator. Раскрытие правил R-OBS-CTX-1..4 и R-OBS-CTX-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/observability/java/context-propagation/</guid>
<pubDate>Mon, 25 May 2026 19:35:58 GMT</pubDate>
</item>
<item>
<title>SLO и алерты — multi-window burn rate, error budget и runbook'и</title>
<link>https://vikulin-va.ru/standards/backend/observability/java/slo-and-alerts/</link>
<description>SLO в Java/Spring: каждый critical-endpoint имеет SLO (99.9% successful, p95 &lt; 500ms) в течение rolling 30-day window. Multi-window multi-burn-rate alerts по Google SRE Workbook — fast burn (1h, rate &gt; 14.4) и slow burn (6h, rate &gt; 6). Error budget exhaustion — отдельный алерт когда бюджет &lt; 10%. Алерты отдельные от SLO: infrastructure, domain, resilience, Kafka consumer lag, cache hit rate. Запреты: alert на каждый ERROR (alert fatigue), SLO без error budget (100% target — нечем оперировать; 99.9% даёт 43 минуты downtime в месяц), алерты без runbook'ов. Раскрытие правил R-OBS-SLO-1..4 и R-OBS-SLO-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/observability/java/slo-and-alerts/</guid>
<pubDate>Mon, 25 May 2026 19:35:58 GMT</pubDate>
</item>
<item>
<title>Когда CQRS оправдан — три уровня и три порога применения</title>
<link>https://vikulin-va.ru/standards/backend/cqrs/java/when-cqrs-is-justified/</link>
<description>Когда применять CQRS в Spring Boot-сервисе: lightweight маркеры UseCaseCommand/UseCaseQuery обязательны с Уровня 2, полный split с разделением хранилищ оправдан при read:write ratio ≥ 10:1 или принципиально разной структуре read-проекции, денормализованная read-таблица в той же БД — middle-ground для join'ов 5+ таблиц и тяжёлых aggregations. Запреты: full CQRS «just in case» для нового сервиса, разделение баз без явной причины. Раскрытие правил R-CQRS-WHEN-1..3 и R-CQRS-WHEN-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/cqrs/java/when-cqrs-is-justified/</guid>
<pubDate>Mon, 25 May 2026 18:44:36 GMT</pubDate>
</item>
<item>
<title>Command side в CQRS — write-handler через агрегат и outbox</title>
<link>https://vikulin-va.ru/standards/backend/cqrs/java/command-side/</link>
<description>Как устроен command-handler в CQRS: Command — record, реализует UseCaseCommand&lt;R&gt;; меняет один агрегат; загружает через Repository.findById(id, FOR_UPDATE); вызывает доменный метод; сохраняет; пишет в outbox для синхронизации read-model. Command возвращает минимум: id или статус, не полный read-DTO. Запреты: отдельный SELECT для чтения, возврат read-DTO, мутация нескольких агрегатов без саги. Раскрытие правил R-CQRS-CMD-1..5 и R-CQRS-CMD-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/cqrs/java/command-side/</guid>
<pubDate>Mon, 25 May 2026 18:44:36 GMT</pubDate>
</item>
<item>
<title>Query side в CQRS — read-handler через ViewRepository и read-DTO</title>
<link>https://vikulin-va.ru/standards/backend/cqrs/java/query-side/</link>
<description>Как устроен query-handler в CQRS: Query — record, реализует UseCaseQuery&lt;R&gt;; handler с @Transactional(readOnly=true); грузит данные через &lt;X&gt;ViewRepository, отдельный от write-Repository; возвращает read-DTO (record), не агрегат; не вызывает доменные методы. Запреты: query делает write, грузит агрегат целиком и маппит в DTO, возвращает агрегат или Entity наружу. Раскрытие правил R-CQRS-QRY-1..4 и R-CQRS-QRY-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/cqrs/java/query-side/</guid>
<pubDate>Mon, 25 May 2026 18:44:36 GMT</pubDate>
</item>
<item>
<title>Read-model в CQRS — где хранить и как обновлять денормализованную проекцию</title>
<link>https://vikulin-va.ru/standards/backend/cqrs/java/read-model/</link>
<description>Read-model в CQRS: денормализованная проекция, оптимизированная под чтение. Где хранить: PG-таблица для tabular queries, materialized view для тяжёлых aggregations, Redis для key-lookup, ElasticSearch для full-text search. Schema независимая от write-стороны, eventual consistency 100ms-1s через outbox + Kafka. Read-model восстановима из write-side скриптом replay. Запреты: read-model как source-of-truth, бизнес-логика в триггерах read-таблицы, bidirectional sync read → write. Раскрытие правил R-CQRS-RM-1..4 и R-CQRS-RM-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/cqrs/java/read-model/</guid>
<pubDate>Mon, 25 May 2026 18:44:36 GMT</pubDate>
</item>
<item>
<title>Синхронизация read-model через события — outbox + Kafka + idempotent consumer</title>
<link>https://vikulin-va.ru/standards/backend/cqrs/java/sync-via-events/</link>
<description>Как синхронизировать read-model с write-side в CQRS: write-handler commit → outbox-таблица атомарно, outbox-relay публикует в Kafka, read-side consumer (этот же сервис или другой) обновляет read-model. Idempotent consumer обязателен через processed_event таблицу или idempotent UPDATE по version. Batch-rebuild для bootstrap и disaster recovery. Eventual consistency декларируется в API. Read-your-writes — через sticky session, polling или non-CQRS endpoint. Запреты: synchronous UPDATE read-model в write-tx, sync через PG triggers, schema-coupled events. Раскрытие правил R-CQRS-SYNC-1..5 и R-CQRS-SYNC-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/cqrs/java/sync-via-events/</guid>
<pubDate>Mon, 25 May 2026 18:44:36 GMT</pubDate>
</item>
<item>
<title>Уровень и эволюция CQRS — от lightweight маркеров к event-driven read-model</title>
<link>https://vikulin-va.ru/standards/backend/cqrs/java/tier-and-evolution/</link>
<description>Эволюция CQRS по уровням зрелости: Уровень 1 — без CQRS; Уровень 2 — lightweight маркеры UseCaseCommand/UseCaseQuery обязательны, один Repository, readOnly=true на query; Уровень 3 split — отдельный &lt;X&gt;ViewRepository в core/, read-DTO; Уровень 3 event-driven — отдельная read-таблица или хранилище, sync через outbox+Kafka. Эволюция всегда снизу вверх. Запреты: маркеры на Уровне 1 без enforcement, event-driven read-model с одним Repository для R+W. Раскрытие правил R-CQRS-TIER-1..5 и R-CQRS-TIER-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/cqrs/java/tier-and-evolution/</guid>
<pubDate>Mon, 25 May 2026 18:44:36 GMT</pubDate>
</item>
<item>
<title>Entity в DDD — стабильный ID, equals по ID, бизнес-методы вместо сеттеров</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/entity/</link>
<description>Что такое Entity в тактическом DDD: наследование Entity&lt;ID&gt;, final-поле id, equals/hashCode по идентификатору (никогда по полям), валидация инвариантов в конструкторе, изменение состояния только через бизнес-методы. Запреты: переопределять equals в наследниках, ссылаться на другие агрегаты объектами, держать публичные сеттеры, писать анемичный класс из одних геттеров. Раскрытие правил R-ENT-1..5 и R-ENT-X1..X5.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/entity/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Value Object в DDD — immutable, equals по значению, Java record как идеальный носитель</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/value-object/</link>
<description>Что такое Value Object в тактическом DDD: маркер ValueObject, immutability (final class, final fields), equals по всем значимым полям, валидация инвариантов в конструкторе, мутации через возврат нового экземпляра. Java record + ValueObject — идеальная связка. Запреты: id или жизненный цикл в VO, primitive obsession, мутабельные коллекции без обёртки. Раскрытие правил R-VO-1..5 и R-VO-X1..X3 на примерах Money, Email, Address.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/value-object/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Aggregate Root в DDD — граница транзакции и точка входа в агрегат</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/aggregate-root/</link>
<description>Что такое Aggregate Root в тактическом DDD: наследование AggregateRoot&lt;ID&gt;, все внешние операции через методы корня, внутренние Entity скрыты, доменные события регистрируются только в корне через registerEvent. Транзакция изменяет один агрегат, между агрегатами — eventual consistency через события. Ссылки между агрегатами — по ID. Запреты: God aggregate, мутабельные коллекции наружу, регистрация событий вне корня, изменение чужого агрегата напрямую. Раскрытие правил R-AGG-1..5 и R-AGG-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/aggregate-root/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Domain Event в DDD — иммутабельный факт в прошлом, который регистрируется корнем агрегата</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/domain-event/</link>
<description>Что такое Domain Event в тактическом DDD: наследование DomainEvent, имя в прошедшем времени (OrderPaid не PayOrder), immutability, бизнес-контекст в полях (не ссылка на агрегат), публикация через DomainEventPublisher после save(), clearDomainEvents() после публикации. Запреты: ссылка на агрегат внутри события, публикация из сервиса/контроллера, @TransactionalEventListener AFTER_COMMIT для критичных эффектов (нужен Outbox). Раскрытие правил R-EVT-1..5 и R-EVT-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/domain-event/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Repository в DDD — интерфейс в core, реализация в адаптере, агрегат сохраняется целиком</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/repository/</link>
<description>Что такое Repository в тактическом DDD: наследование AggregateRepository&lt;T, ID&gt;, интерфейс в domain-пакете, реализация в out-adapter, один репозиторий = один корень агрегата, save сохраняет агрегат целиком и публикует собранные события + clearDomainEvents, методы названы в терминах домена. Запреты: возврат DAO/jOOQ типов наружу, методы про конкретную таблицу, Specification для SQL. Раскрытие правил R-REP-1..5 и R-REP-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/repository/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Domain Service в DDD — только когда логика касается двух агрегатов</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/domain-service/</link>
<description>Что такое Domain Service в тактическом DDD: создаётся, ТОЛЬКО когда правило касается двух и более агрегатов и не помещается в один корень. Stateless, принимает доменные объекты, имя выражает доменную операцию (TransferService, PricingService). Запреты: оркестрация (загрузка из репозитория, транзакции, публикация событий — это Application Service), Domain Service как свалка вместо rich domain. Раскрытие правил R-DS-1..3 и R-DS-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/domain-service/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Factory в DDD — когда конструктор не справляется</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/factory/</link>
<description>Что такое Factory в тактическом DDD: вводится ТОЛЬКО когда конструктор не справляется — нужны данные из другого агрегата, выбор подкласса по политике, сборка из нескольких частей. Factory возвращает уже валидный агрегат с зарегистрированными начальными событиями (OrderCreated). Запрет — Factory ради Factory: если new Order(...) работает, лишний слой не нужен. Раскрытие правил R-FAC-1..2 и R-FAC-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/factory/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Specification в DDD — переиспользуемое доменное правило с комбинаторами</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/specification/</link>
<description>Что такое Specification в тактическом DDD: наследование Specification&lt;T&gt;, метод isSatisfiedBy(T), комбинаторы and/or/not, используется ТОЛЬКО когда правило применяется в двух и более местах либо нужны комбинации. Запреты: Specification для генерации SQL (это Query Side, не доменное правило), Specification для одного if в одном месте (преждевременная абстракция). Раскрытие правил R-SPEC-1..2 и R-SPEC-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/specification/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Структура пакетов в DDD — по домену, не по типу</title>
<link>https://vikulin-va.ru/standards/backend/ddd-tactical/java/module-structure/</link>
<description>Как раскладывать DDD-код по пакетам: верхний уровень — Bounded Context, внутри — domain/ (aggregate, entity, valueobject, event, repository, service, specification) и usecase/ (command, query). Запрет на верхнеуровневые папки entity/, service/, repository/ — это группировка по типу, классический антипаттерн. core/ без зависимостей от Spring/JPA/jOOQ. Раскрытие правил R-MOD-1..2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/ddd-tactical/java/module-structure/</guid>
<pubDate>Mon, 25 May 2026 17:10:33 GMT</pubDate>
</item>
<item>
<title>Когда переходить на Hexagonal Architecture</title>
<link>https://vikulin-va.ru/standards/backend/hexagonal/java/when-to-use-hexagonal/</link>
<description>Hexagonal — паттерн с ceremony. Когда выгода (testability, изоляция домена, тех-опции) реально перевешивает: интеграции с 2+ системами, богатая domain-логика, 3+ способа входа, команда 3+ человек. Когда рано: монолит из 3 endpoints, 1-2 разработчика, неустоявшаяся бизнес-логика. Запрет cargo-cult и частичного Hexagonal. Раскрытие правил R-HEX-WHEN-1..3 и R-HEX-WHEN-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/hexagonal/java/when-to-use-hexagonal/</guid>
<pubDate>Mon, 25 May 2026 16:01:20 GMT</pubDate>
</item>
<item>
<title>Структура модулей в Hexagonal Architecture</title>
<link>https://vikulin-va.ru/standards/backend/hexagonal/java/module-structure/</link>
<description>Multi-module gradle для Hexagonal: core/ без Spring, persistence/, отдельные *-in-adapter и *-out-adapter на каждую систему/тип входа, bootstrap/ как composition root. Почему один модуль с папками core/adapter — антипаттерн, и почему стрелка зависимостей строго bootstrap → core ← adapters. Раскрытие правил R-HEX-MOD-1..5 и R-HEX-MOD-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/hexagonal/java/module-structure/</guid>
<pubDate>Mon, 25 May 2026 16:01:20 GMT</pubDate>
</item>
<item>
<title>Core слой в Hexagonal Architecture</title>
<link>https://vikulin-va.ru/standards/backend/hexagonal/java/core-layer/</link>
<description>Что попадает в core/: DDD-агрегаты, ports out-интерфейсы, use cases, application-DTO. От чего core/ зависит (JDK, Lombok, DDD-библиотеки) и от чего НЕ зависит (Spring, JOOQ, Jackson, OkHttp, Kafka). Почему rich domain методы внутри агрегата, а не в *Service. Почему generated POJO и HTTP-DTO в core/ — антипаттерн. Раскрытие правил R-HEX-CORE-1..4 и R-HEX-CORE-X1..X5.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/hexagonal/java/core-layer/</guid>
<pubDate>Mon, 25 May 2026 16:01:20 GMT</pubDate>
</item>
<item>
<title>Ports в Hexagonal Architecture — interfaces в core/</title>
<link>https://vikulin-va.ru/standards/backend/hexagonal/java/ports/</link>
<description>Что такое outbound port в Hexagonal, почему port лежит в core/&lt;bc&gt;/port/out/, как именовать (&lt;X&gt;Repository, &lt;Y&gt;Port, &lt;Z&gt;EventPublisher), почему методы port'а оперируют domain-типами, а не generated DTO внешней системы. Зачем abstract PortException в core и конкретные подклассы в out-adapter. Почему inbound port — это UseCase, отдельный интерфейс не нужен. Раскрытие правил R-HEX-PORT-1..4 и R-HEX-PORT-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/hexagonal/java/ports/</guid>
<pubDate>Mon, 25 May 2026 16:01:20 GMT</pubDate>
</item>
<item>
<title>Adapters In в Hexagonal — REST / Kafka consumer / CLI как entry-points</title>
<link>https://vikulin-va.ru/standards/backend/hexagonal/java/adapters-in/</link>
<description>Что такое in-adapter в Hexagonal: per-purpose модули (user-api / admin-api / kafka-in / cli-in), Controller через generated &lt;Tag&gt;Api, маппер REST-DTO ↔ Use Case command, что нельзя класть в Controller (бизнес-логика, прямой вызов Repository, domain entity наружу), почему in-adapter не зависит от out-adapter. Раскрытие правил R-HEX-AIN-1..4 и R-HEX-AIN-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/hexagonal/java/adapters-in/</guid>
<pubDate>Mon, 25 May 2026 16:01:20 GMT</pubDate>
</item>
<item>
<title>Adapters Out в Hexagonal — реализация port-интерфейсов из core</title>
<link>https://vikulin-va.ru/standards/backend/hexagonal/java/adapters-out/</link>
<description>Что такое out-adapter в Hexagonal: per-system модули (persistence/, sber-out-adapter/, kafka-out-adapter/, s3-out-adapter/), implements port из core, mapper для generated DTO ↔ domain. Что нельзя класть в out-adapter (бизнес-логика, generated DTO в port-методе, координация с другим адаптером). Почему один адаптер на систему. Раскрытие правил R-HEX-AOUT-1..4 и R-HEX-AOUT-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/hexagonal/java/adapters-out/</guid>
<pubDate>Mon, 25 May 2026 16:01:20 GMT</pubDate>
</item>
<item>
<title>Bootstrap / Composition Root в Hexagonal</title>
<link>https://vikulin-va.ru/standards/backend/hexagonal/java/bootstrap-composition-root/</link>
<description>Что лежит в bootstrap-модуле: @SpringBootApplication, application.yml, @Configuration для wiring, Dockerfile. Почему bootstrap зависит от всех модулей, а никто — от bootstrap. Почему бизнес-логика в bootstrap и @SpringBootApplication в core/adapter — антипаттерны. Раскрытие правил R-HEX-BOOT-1..3 и R-HEX-BOOT-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/hexagonal/java/bootstrap-composition-root/</guid>
<pubDate>Mon, 25 May 2026 16:01:20 GMT</pubDate>
</item>
<item>
<title>Архитектурные тесты Hexagonal через ArchUnit</title>
<link>https://vikulin-va.ru/standards/backend/hexagonal/java/architecture-tests/</link>
<description>Зачем ArchUnit-тесты в Hexagonal-сервисе и какие правила они enforce-ят (core без Spring/JOOQ, port — interface в core, in-adapter не зависит от out-adapter, controller implements generated &lt;Tag&gt;Api). Почему один required CI check ловит то, что человек-ревьюер пропустит. Раскрытие правил R-HEX-TEST-1..3 и R-HEX-TEST-X1.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/hexagonal/java/architecture-tests/</guid>
<pubDate>Mon, 25 May 2026 16:01:20 GMT</pubDate>
</item>
<item>
<title>Когда нужны распределённые паттерны — три условия и три альтернативы</title>
<link>https://vikulin-va.ru/standards/backend/distributed-patterns/java/when-to-use/</link>
<description>Когда применять распределённые паттерны: бизнес-операция охватывает 2+ сервиса и невозможно завершить локальной транзакцией; в одном сервисе и одном PostgreSQL — обычный @Transactional. Альтернативы перед введением: объединение в один BC, modular monolith, eventual consistency без саги. Запреты: распределённые паттерны для одного сервиса, микросервисы из амбиций. Раскрытие правил R-DIST-WHEN-1..3 и R-DIST-WHEN-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/distributed-patterns/java/when-to-use/</guid>
<pubDate>Mon, 25 May 2026 19:24:51 GMT</pubDate>
</item>
<item>
<title>Saga — оркестрация vs хореография, выбор и реализация</title>
<link>https://vikulin-va.ru/standards/backend/distributed-patterns/java/saga/</link>
<description>Saga — управление long-running cross-service операцией через серию локальных транзакций + compensation. Orchestration с центральным координатором — для саг 4+ шагов и branching; choreography через события — для 2-3 шагов. State хранится в saga_&lt;name&gt; таблице PostgreSQL для видимости, recovery и audit. SagaId сквозной для трассировки. Запреты: 2PC/XA вместо саги, saga без compensation, state in-memory, saga смешана с use case. Раскрытие правил R-DIST-SAGA-1..5 и R-DIST-SAGA-X1..X4.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/distributed-patterns/java/saga/</guid>
<pubDate>Mon, 25 May 2026 19:24:51 GMT</pubDate>
</item>
<item>
<title>Idempotency в распределённых системах — таблицы processed_event и idempotency_record</title>
<link>https://vikulin-va.ru/standards/backend/distributed-patterns/java/idempotency/</link>
<description>Idempotency обязательна в распределённой системе: at-least-once приводит к дубликатам. Каждое сообщение имеет ID — eventId UUID v7 для Kafka, Idempotency-Key header для HTTP money, sagaId+stepName для шагов саги. Receiver хранит processed_event и проверяет перед обработкой; для HTTP — idempotency_record с (key, command_hash, response), конфликт ключа с другой командой — 409. Money — двойная защита: client Idempotency-Key + внутренний unique constraint. TTL 24-72 часа. Запреты: receiver без dedup для money, только receiver-side, новый UUID каждый retry. Раскрытие правил R-DIST-IDEM-1..5 и R-DIST-IDEM-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/distributed-patterns/java/idempotency/</guid>
<pubDate>Mon, 25 May 2026 19:24:51 GMT</pubDate>
</item>
<item>
<title>Eventual consistency — декларация в OpenAPI, read-your-writes, bounded staleness</title>
<link>https://vikulin-va.ru/standards/backend/distributed-patterns/java/eventual-consistency/</link>
<description>Eventual consistency требует явного контракта: декларация в OpenAPI с ожидаемой задержкой, bounded staleness SLO «не более 5 секунд между write и появлением в read-проекции», read-your-writes реализуется через sticky session, polling, synchronous wait или альтернативный endpoint из write-side. Causal consistency через version-поля. Запреты: молчаливая eventual consistency, strict immediate через 2PC. Раскрытие правил R-DIST-EC-1..4 и R-DIST-EC-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/distributed-patterns/java/eventual-consistency/</guid>
<pubDate>Mon, 25 May 2026 19:24:51 GMT</pubDate>
</item>
<item>
<title>Outbox и Inbox — атомарная публикация и приём в распределённой системе</title>
<link>https://vikulin-va.ru/standards/backend/distributed-patterns/java/outbox-inbox/</link>
<description>Outbox решает атомарность «БД commit + message publish»: команда commits в БД и INSERT в outbox_event атомарно, outbox-relay (@Scheduled с FOR UPDATE SKIP LOCKED) публикует в Kafka и помечает published_at. Inbox — обратное: consumer пишет полученное сообщение в inbox_event + processed=false, отдельный handler обрабатывает. В большинстве случаев — inbox избыточен, достаточно processed_event dedup. Single source of truth — БД сервиса, Kafka — транспорт. Запреты: direct send из command-handler, @TransactionalEventListener для Kafka. Раскрытие правил R-DIST-OBX-1..3 и R-DIST-OBX-X1..X2.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/distributed-patterns/java/outbox-inbox/</guid>
<pubDate>Mon, 25 May 2026 19:24:51 GMT</pubDate>
</item>
<item>
<title>Compensation в saga — semantic state-change, идемпотентность, DLQ</title>
<link>https://vikulin-va.ru/standards/backend/distributed-patterns/java/compensation/</link>
<description>Compensation — отмена эффекта предыдущего шага саги. Каждая command имеет парную compensation (chargePayment ↔ refundPayment, reserveInventory ↔ releaseInventory). Compensation идемпотентен — saga может повторить compensation при retry. Semantic compensation, не технический rollback: refund — новая транзакция, не «откат». Audit trail обязателен — статус REFUNDED с reference. При failure compensation — DLQ и manual review. Запреты: saga без compensation, DELETE как compensation, compensation без retry-механики. Раскрытие правил R-DIST-COMP-1..4 и R-DIST-COMP-X1..X3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/distributed-patterns/java/compensation/</guid>
<pubDate>Mon, 25 May 2026 19:24:51 GMT</pubDate>
</item>
<item>
<title>Distributed transactions — почему 2PC, JTA и XA не подходят для микросервисов</title>
<link>https://vikulin-va.ru/standards/backend/distributed-patterns/java/distributed-transactions/</link>
<description>2PC, JTA, XA в UCP запрещены: Kafka не поддерживает XA, 2PC synchronous block не масштабируется, transaction coordinator — single point of failure, сложно operate в Kubernetes. ChainedTransactionManager — best-effort, не атомарность; failure между commit-ами оставляет inconsistency. Альтернативы: saga с локальными транзакциями (стандарт UCP), outbox + idempotent consumer для event-driven sync, modular monolith для tight coupling — один PG с локальным @Transactional. Раскрытие правил R-DIST-TX-X1..X3 и R-DIST-TX-1..3.</description>
<guid isPermaLink="true">https://vikulin-va.ru/standards/backend/distributed-patterns/java/distributed-transactions/</guid>
<pubDate>Mon, 25 May 2026 19:24:51 GMT</pubDate>
</item>
<item>
<title>Метод системного дизайна: от требований к архитектуре</title>
<link>https://vikulin-va.ru/system-design/method/</link>
<description>Пошаговый метод системного дизайна: требования, оценки нагрузки на салфетке, контракты, модель данных, схема, горячие точки, отказы — и принципы, которые держат процесс.</description>
<guid isPermaLink="true">https://vikulin-va.ru/system-design/method/</guid>
<pubDate>Sat, 6 Jun 2026 18:30:47 GMT</pubDate>
</item>
<item>
<title>Строительные блоки системного дизайна и их цена</title>
<link>https://vikulin-va.ru/system-design/building-blocks/</link>
<description>Словарь системного дизайна: балансировка, кеш, репликация и шардинг, очереди, поиск, аналитика, CDN. Что каждый блок покупает, чем платят и по какому числу он появляется.</description>
<guid isPermaLink="true">https://vikulin-va.ru/system-design/building-blocks/</guid>
<pubDate>Sat, 6 Jun 2026 18:30:47 GMT</pubDate>
</item>
<item>
<title>Системный дизайн на практике: проектируем систему уведомлений</title>
<link>https://vikulin-va.ru/system-design/example-notifications/</link>
<description>Весь метод системного дизайна на одной задаче: уведомления для 10 млн пользователей — оценки на салфетке, контракты, модель данных, схема с очередями, отказы и деградация.</description>
<guid isPermaLink="true">https://vikulin-va.ru/system-design/example-notifications/</guid>
<pubDate>Sat, 6 Jun 2026 18:30:47 GMT</pubDate>
</item>
<item>
<title>Оформление и защита дизайна: design doc, C4, ревью</title>
<link>https://vikulin-va.ru/system-design/design-docs/</link>
<description>Как превратить системный дизайн в решение: структура design doc, диаграммы C4 по уровням, ADR для развилок, процесс ревью с чек-листом вопросов и типичные провалы защиты.</description>
<guid isPermaLink="true">https://vikulin-va.ru/system-design/design-docs/</guid>
<pubDate>Sat, 6 Jun 2026 18:30:47 GMT</pubDate>
</item>
<item>
<title>Выбор начальной архитектуры: монолит, модульный монолит, микросервисы</title>
<link>https://vikulin-va.ru/architecture-choice/monolith-vs-microservices/</link>
<description>Слойный монолит, модульный монолит или микросервисы: критерии выбора, чек-лист на старте проекта и сценарии перехода. Как Use Case Pattern переживает каждый из этих режимов без переписывания.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/monolith-vs-microservices/</guid>
<pubDate>Mon, 18 May 2026 07:48:58 GMT</pubDate>
</item>
<item>
<title>PostgreSQL или MongoDB: как принять решение</title>
<link>https://vikulin-va.ru/architecture-choice/pg-vs-mongo/</link>
<description>Десять конкретных критериев выбора между PostgreSQL и MongoDB на новом сервисе: природа данных, шаблон запросов, требования к транзакциям, схема, нагрузка, операционная зрелость команды. Чек-лист, типичные ошибки выбора, сценарии где обе БД работают вместе.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/pg-vs-mongo/</guid>
<pubDate>Mon, 18 May 2026 07:48:58 GMT</pubDate>
</item>
<item>
<title>PostgreSQL или ClickHouse: когда добавлять OLAP</title>
<link>https://vikulin-va.ru/architecture-choice/pg-vs-clickhouse/</link>
<description>Когда аналитику пора выносить из PostgreSQL в ClickHouse: восемь критериев, чек-лист с баллами, типичные ошибки — ClickHouse как замена PG, кластер на пять миллионов строк.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/pg-vs-clickhouse/</guid>
<pubDate>Sat, 6 Jun 2026 16:38:02 GMT</pubDate>
</item>
<item>
<title>Поиск: PostgreSQL FTS или Elasticsearch</title>
<link>https://vikulin-va.ru/architecture-choice/pg-fts-vs-elasticsearch/</link>
<description>Когда полнотекстового поиска PostgreSQL (tsvector, pg_trgm) достаточно, а когда нужен Elasticsearch: восемь критериев, чек-лист, типичные ошибки — ES ради одного LIKE.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/pg-fts-vs-elasticsearch/</guid>
<pubDate>Sat, 6 Jun 2026 16:38:02 GMT</pubDate>
</item>
<item>
<title>Файлы: в базе данных или в object storage</title>
<link>https://vikulin-va.ru/architecture-choice/db-vs-s3/</link>
<description>Где хранить файлы — bytea в PostgreSQL или S3: семь критериев, граница по размеру и трафику, целостность «БД + S3» через двухфазную загрузку и outbox, типичные ошибки.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/db-vs-s3/</guid>
<pubDate>Sat, 6 Jun 2026 16:38:02 GMT</pubDate>
</item>
<item>
<title>Между сервисами: синхронный вызов или события</title>
<link>https://vikulin-va.ru/architecture-choice/sync-vs-async/</link>
<description>REST-вызов или событие через брокер: семь критериев выбора взаимодействия сервисов, чек-лист, типичные ошибки — синхронная сага из пяти сервисов, RPC поверх Kafka.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/sync-vs-async/</guid>
<pubDate>Sat, 6 Jun 2026 16:38:02 GMT</pubDate>
</item>
<item>
<title>Веб-стек: Spring MVC, WebFlux или виртуальные потоки</title>
<link>https://vikulin-va.ru/architecture-choice/mvc-vs-webflux/</link>
<description>Выбор веб-стека Spring: что виртуальные потоки Java 21 закрыли из аргументов WebFlux, где reactive ещё оправдан, чек-лист и ошибки — WebFlux «для скорости», block() в цепочке.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/mvc-vs-webflux/</guid>
<pubDate>Sat, 6 Jun 2026 16:38:02 GMT</pubDate>
</item>
<item>
<title>ADR: как фиксировать архитектурные решения</title>
<link>https://vikulin-va.ru/architecture-choice/adr/</link>
<description>Architecture Decision Records: формат (контекст, решение, последствия), статусы, где хранить, когда писать и когда нет. Пример ADR на реальной развилке и ошибки ведения.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/adr/</guid>
<pubDate>Sat, 6 Jun 2026 16:43:55 GMT</pubDate>
</item>
<item>
<title>Что делает архитектор — и какие задачи закрывают AI-скиллы</title>
<link>https://vikulin-va.ru/architecture-choice/architect-role/</link>
<description>Обязанности архитектора в команде: карта системы, развилки и ADR, границы контекстов, бизнес-процессы, impact-анализ, согласованность — и какие ucp-скиллы закрывают каждую.</description>
<guid isPermaLink="true">https://vikulin-va.ru/architecture-choice/architect-role/</guid>
<pubDate>Sat, 6 Jun 2026 16:43:55 GMT</pubDate>
</item>
<item>
<title>Вход тимлида в проблемную команду: разбор кейса</title>
<link>https://vikulin-va.ru/teamlead/taking-over-team/</link>
<description>Разбор кейса: новый тимлид принимает команду с экс-лидом в составе, перегруженным продакт-овнером, потоком чужих задач и подорванным доверием стейкхолдеров. План 30/60/90 и приёмы.</description>
<guid isPermaLink="true">https://vikulin-va.ru/teamlead/taking-over-team/</guid>
<pubDate>Sat, 6 Jun 2026 18:02:08 GMT</pubDate>
</item>
<item>
<title>Архитектурный аудит сервиса или системы</title>
<link>https://vikulin-va.ru/services/architecture-audit/</link>
<description>Разбор существующего кода и архитектуры с письменным отчётом и приоритизацией проблем. Команда после аудита знает что чинить в первую очередь и в каком порядке.</description>
<guid isPermaLink="true">https://vikulin-va.ru/services/architecture-audit/</guid>
<pubDate>Tue, 28 Apr 2026 09:28:08 GMT</pubDate>
</item>
<item>
<title>Внедрение Use Case Pattern в команде</title>
<link>https://vikulin-va.ru/services/usecase-pattern-implementation/</link>
<description>Workshop + сопровождение. После — команда самостоятельно применяет UCP, ведёт спецификацию-как-код, использует AI-скиллы для review каждой PR.</description>
<guid isPermaLink="true">https://vikulin-va.ru/services/usecase-pattern-implementation/</guid>
<pubDate>Tue, 28 Apr 2026 09:28:08 GMT</pubDate>
</item>
<item>
<title>Технический ментор для тимлида и архитектора</title>
<link>https://vikulin-va.ru/services/mentoring/</link>
<description>Регулярные сессии 1-на-1: sparring-партнёр по конкретным архитектурным решениям. Не общая лекция, а разбор того, что прямо сейчас на столе.</description>
<guid isPermaLink="true">https://vikulin-va.ru/services/mentoring/</guid>
<pubDate>Tue, 28 Apr 2026 09:28:08 GMT</pubDate>
</item>
<item>
<title>Code review как сервис</title>
<link>https://vikulin-va.ru/services/code-review/</link>
<description>Async-ревью PR-ов с цитированием правил методологии. Команда поднимает уровень кода без необходимости держать senior full-time.</description>
<guid isPermaLink="true">https://vikulin-va.ru/services/code-review/</guid>
<pubDate>Tue, 28 Apr 2026 09:28:08 GMT</pubDate>
</item>
<item>
<title>Кейс: enterprise без отдельных системных аналитиков</title>
<link>https://vikulin-va.ru/cases/system-analysts-removed/</link>
<description>Enterprise-команда 25+ инженеров. Внедрили Use Case спецификацию-как-код и AI-скиллы для генерации артефактов и review. Отдел системного анализа расформирован — функция распределена между разработчиками и AI-скиллами.</description>
<guid isPermaLink="true">https://vikulin-va.ru/cases/system-analysts-removed/</guid>
<pubDate>Tue, 28 Apr 2026 09:30:00 GMT</pubDate>
</item>
<item>
<title>Кейс: код стартапа остаётся понятным</title>
<link>https://vikulin-va.ru/cases/startup-clean-codebase/</link>
<description>Стартап 4-8 разработчиков, MVP с быстрой эволюцией требований. Внедрили UCP с правильным уровнем по модулям и AI-скиллы для review с первого дня. Через 1.5 года код адаптируется без переписывания.</description>
<guid isPermaLink="true">https://vikulin-va.ru/cases/startup-clean-codebase/</guid>
<pubDate>Tue, 28 Apr 2026 09:30:00 GMT</pubDate>
</item>
</channel></rss>
