Юрий Морозов

Юрий Морозов

30 лет в ИТ. Прошёл путь от разработчика через тим/тех-лида и руководителя управлений до CTO — знаю каждую роль изнутри. До сих пор пишу код.

Сильные стороны: запуск с нуля (команды, процессы, инфраструктура), трансформация легаси и зрелых организаций, построение надёжных высоконагруженных систем, работа в B2C и B2B одновременно. Управлял коллективами 200+ человек, системами с аудиторией 25+ млн пользователей, реализовывал B2C и B2B стратегии в страховании, телекоме и ритейле, включая электронную коммерцию.

Компании: АльфаСтрахование, СОГАЗ, МегаФон, CUSTIS (Спортмастер, Газпром, Банк России).

Сейчас в роли внешнего CTO помогаю компаниям преодолевать технологические и организационные трудности — от стратегии до кода.

Стратегия
Roadmap, бюджет, техдолг
Архитектура
Системный дизайн, масштабирование, аудит
Инфраструктура
CI/CD, деплой, hosting
Разработка
Полный цикл: от идеи до прода, сам
Безопасность
ФЗ-152, Shadow AI, защита данных
Процессы
Delivery, Agile, observability
Люди
Менторинг, культура, найм
AI / Agents
AI, агентные системы, автоматизация

Раньше я закрывал весь этот стек сам или через команды, каждый на своём участке. Теперь мне эти задачи закрывает ИИ.
Я остаюсь тем, кто понимает зачем, что и как правильно — но execution стал быстрее и дешевле.

Пример, от инфраструктуры через полный цикл разработки до деливери. API Gateway за 3 недели part-time.

Демонстрация

Карьера в цифрах
Страхование Телеком Ритейл Финсектор IT-консалтинг

Масштаб управления

200+ человек в зоне ответственности, производство полного цикла (CUSTIS)

150+ человек — разработка и сопровождение полного цикла (АльфаСтрахование, 18 лет)

35 человек — 3 команды с нуля за 3 месяца (СОГАЗ)

10+ кросс-функциональных Agile-команд (АльфаСтрахование)

~40 корпоративных систем (SAP FSCM, Oracle E-Business Suite, Infor SalesLogix, QlikView, OpenText и др.)

до 5 000 пользователей внутренних систем, 25+ млн клиентов на сайте (2019 ↗)

Результаты

Time-to-market: 6 мес → 2 недели (Agile-трансформация)

Доступность: 94% → 99.9% — SRE-группа с нуля

25+ млн клиентов на alfastrah.ru — #1 по посещаемости среди страховых (Яндекс.Радар, 2018 ↗)

Приложение — победитель «Рейтинг Рунета» 2019 ↗ в категории «Финансы»

MVP B2B-портала ↗ за 4 недели → 860K+ визитов/мес, работает до сих пор

ISO/IEC 20000-1:2011 — сертификация разработки

Продукты-лидеры

alfastrah.ru — #1 по посещаемости среди страховых, 25+ млн клиентов, работает до сих пор

Приложение АльфаСтрахование — победитель «Рейтинг Рунета» 2019, работает до сих пор

B2B-портал «АльфаПолис» ↗ — 860K+ визитов/мес, вырос в экосистему, работает до сих пор

Команды — 10+ лет вместе, многие работают до сих пор


Кейс: СОГАЗ Антикризисный CTO

Принял хаос от 10 подрядчиков (legacy, проблемы с безопасностью). Построил 3 команды с нуля, вывел на релизы за 3 месяца. Выявил и закрыл критическую утечку персданных за месяц.

Кейс: МегаФон Разработка

Перевёл кредитный брокер от подрядчика внутрь — тысячи кредитов, десятки тысяч расчётов в сутки. 60 модулей, 17 микросервисов, интеграции с 5 банками — за 2 месяца.

Кейс: CUSTIS Аудит + Стратегия

Аудит производства (200+ человек, 5 автономных направлений, несовместимые стеки, текучка 70%, 3 мес на вхождение). Разработал и защитил стратегию унификации. Собрал Productivity Team — выделенную команду под реализацию стратегии. Стратегия принята, команда передана заказчику и работает.

Кейс: АльфаСтрахование штатный CTO

Масштабная Agile-трансформация традиционной компании. BigData/AI команда с нуля (Hadoop, антифрод). Продукты-лидеры рынка в B2B и B2C.

Примеры и код
API Gateway
PROJECT_001

API Gateway

Self-service платформа без лицензионных затрат. Управление маршрутами, клиентами, аутентификация, rate limiting. Трудоёмкость 3 недели part-time.

Kotlin, Spring Boot 3.4, React, PostgreSQL, Redis, Docker

Claude Bot
PROJECT_002

Claude Bot

Удаленное управление работой агентов Claude через бота в Telegram.

n8n, Claude AI, Telegram API, FastAPI, Docker

WatchOfWatch
PROJECT_003

Интерактивный виджет

350 часов в матрице 50×7. Визуализация времени как живого паттерна.

TypeScript, React, Canvas API, Astro Islands, Tailwind CSS

API Gateway — Architecture
System Context Level 1
HTTPS + Bearer JWT HTTPS (OIDC) JWT validation / OIDC Proxy requests Prometheus scrape + OTLP push CI/CD deploy (secrets from Vault) API Consumer Внешний клиент, вызывающий API Admin User Developer / Security / Admin API Gateway [System] Spring Cloud Gateway Reactive Stack Keycloak [External] IAM / SSO OIDC + JWT Upstream Services [External] Backend API сервисы Monitoring [External] Prometheus + Grafana + Jaeger CI/CD & Secrets [External] GitLab CI + Vault + Nexus ЛЕГЕНДА Person Internal System External System
Container Diagram Level 2
HTTPS + Bearer HTTPS (OIDC) HTTP Static files API calls HTTP /api/v1 Rate limit (Lua) JWKS validation Proxy request R2DBC CRUD PUBLISH event SUBSCRIBE API Consumer OAuth2 client Admin User Dev / Security / Admin Traefik 3 [External] Reverse proxy · TLS termination Admin UI [Container] React 18 + Ant Design SPA Gateway Core [Container] Spring Cloud Gateway WebFlux · Netty · Port 8080 Admin Service [Container] Spring WebFlux R2DBC · Port 8081 PostgreSQL 16 [Database] Routes · Audit logs 14 Flyway migrations Redis 7 [Database] Rate limiting · Pub/Sub cache invalidation Keycloak 24 [External] OIDC + JWKS JWT validation Upstream Services [External] Proxied backends ЛЕГЕНДА Person Container External Data Store Async (Pub/Sub)

Rate Limiting: Token Bucket + Per-Consumer

Двухуровневая система: глобальный per-route лимит через Redis Lua EVALSHA (атомарный Token Bucket) и per-consumer лимиты с отдельным ConsumerRateLimitCacheManager. При недоступности Redis — автоматический fallback на Caffeine in-memory с 50% от лимита.

Lua скрипт обеспечивает атомарность без distributed locks. Per-consumer лимиты позволяют давать Premium-клиентам больше capacity. Caffeine fallback гарантирует работу gateway даже при сбое Redis — degraded mode лучше чем полный отказ.

Полностью Reactive стек

Spring Cloud Gateway + WebFlux + Netty + R2DBC. Все I/O неблокирующее: HTTP, PostgreSQL, Redis. Нет ThreadLocal — используем Reactor Context + MDC bridging для correlation ID propagation через всю цепочку.

Reactive стек даёт максимальный throughput при минимальном числе потоков. Для API Gateway это критично — один инстанс обрабатывает тысячи concurrent соединений. Event loop модель Netty эффективнее thread-per-request.

Hot Reload конфигурации

Admin Service публикует события в Redis Pub/Sub при изменении маршрутов, rate limits и consumer limits (3 отдельных канала). Gateway Core подписан на все три — RouteCacheManager обновляет AtomicRef<routes> за < 100ms без перезапуска.

AtomicRef.set() — lock-free обновление, совместимое с reactive стеком (нет synchronized). Redis Pub/Sub — минимальная латентность по сравнению с polling. Три отдельных канала — targeted invalidation вместо flush всего кеша.

Security: Keycloak + RBAC

API consumers используют client_credentials grant → JWT Bearer. Admin UI — OIDC PKCE flow через Keycloak. Gateway Core валидирует JWT через JWKS endpoint. Admin Service использует @RequireRole аннотацию с AOP аспектом и иерархией ролей: ADMIN > SECURITY > DEVELOPER.

Keycloak — централизованный IAM для всех сервисов инфраструктуры. JWKS validation не требует обращения к Keycloak при каждом запросе (кеш публичных ключей). RBAC через AOP — декларативно и не загромождает бизнес-логику.

Distributed Tracing: OpenTelemetry + Jaeger

TracingAttributesFilter добавляет span attributes (route, consumer, correlation ID) в каждый запрос. Трейсы отправляются через OTLP в Jaeger. W3C Trace Context propagation в upstream вызовы. Grafana показывает trace links рядом с метриками.

OpenTelemetry — vendor-neutral стандарт, позволяет сменить backend без изменения кода. Jaeger даёт визуализацию latency по span'ам. Correlation ID + trace ID вместе — можно найти запрос и по бизнес-логу и по трейсу.

Observability: Prometheus + Grafana

Оба сервиса экспортируют метрики через /actuator/prometheus. Prometheus scrapes каждые 15s. 5 alert rules: high error rate, P95 latency, gateway down, high consumer cardinality, high metrics cardinality. Grafana dashboard: RPS, P50/P95/P99, errors, per-consumer breakdown.

Pull-модель Prometheus не создаёт backpressure на сервисы. Per-consumer метрики позволяют видеть кто генерирует нагрузку. Alert на cardinality защищает от cardinality explosion при DDoS с random consumer ID.

Инфраструктура и CI/CD

GitLab CI: build → test → SAST (Semgrep) → Docker → deploy. 4 runners с Docker executor. Secrets из HashiCorp Vault (AppRole). Docker образы в Nexus Registry. PostgreSQL: 14 Flyway миграций (V1–V13, строгий порядок). Traefik 3 как reverse proxy с автоматическим TLS.

Vault вместо GitLab CI variables — секреты ротируются централизованно для всех сервисов. SAST блокирует pipeline при Critical/High findings. Flyway с out-of-order: false — предсказуемая схема БД. Centralized infra (Traefik, Postgres, Redis) — shared между проектами.

Component — Gateway Core Level 3a
incoming proxy JWKS check limit EVALSHA SUBSCRIBE Redis down? per-consumer lookup routes data GET routes HTTP Request [External] от Traefik CorrelationIdFilter [Component] Генерация / проброс X-Correlation-ID JwtAuthFilter [Component] Валидация JWT подписи через Keycloak JWKS ConsumerIdentityFilter [Component] Извлечение azp claim → consumer identity MetricsFilter [Component] Запись HTTP метрик По consumer / route RateLimitFilter [Component] Token Bucket (Lua) Per-route + Per-consumer TracingAttributesFilter [Component] OpenTelemetry span attributes LoggingFilter [Component] Structured logging + Correlation ID RouteCacheManager [Service] AtomicRef hot reload < 100ms RateLimitService [Service] Redis EVALSHA TokenBucketScript (Lua) LocalRateLimiter [Service] Caffeine in-memory fallback (50% limit) DynamicRouteLocator [Service] RouteDefinition из Redis → Spring routes ConsumerRateLimitCache [Service] Per-consumer limits Redis + TTL Keycloak JWKS [External] JWT validation Redis [Database] Rate limits + Pub/Sub + Routes Upstream Service [External] Backend API ЛЕГЕНДА Filter Service External Data Store Async (Pub/Sub)
Component — Admin Service Level 3b
JWT / OIDC /routes /rate-limits /approve /consumers /metrics log action log action log action on PUBLISH on change on change R2DBC INSERT R2DBC PUBLISH ×3 JWKS PromQL HTTP Request [External] от Traefik /api/v1 Security Layer [Component] JwtService + @RequireRole Keycloak roles → RBAC RouteController [Component] CRUD маршрутов фильтрация / пагинация RateLimitController [Component] CRUD rate limit политик ApprovalController [Component] Approve / Reject workflow ConsumerController [Component] API consumers keys / secrets MetricsController [Component] Gateway метрики топ маршрутов RouteService [Service] Бизнес-логика маршрутов ApprovalService [Service] DRAFT → PENDING → PUBLISHED ConsumerService [Service] Consumer CRUD + rate limit привязка AuditService [Service] Audit log всех действий MetricsService [Service] PromQL запросы к Prometheus EventPublishers [Service] Route + RateLimit + ConsumerRateLimit events PostgreSQL [Database] routes · audit_logs rate_limits · consumers Redis Pub/Sub [Database] 3 invalidation channels Keycloak [External] OIDC + JWKS roles Prometheus [External] PromQL API метрики gateway ЛЕГЕНДА Component Service External Data Store Async (Event)
Claude Bot — Architecture
Real-time управление AI-агентами через Telegram с двусторонней коммуникацией — streaming вывод Claude прямо в чат, управление сессиями и файлами через бота
Event-Driven Async-First Claude SDK State Machine
DATA FLOW
message webhook POST + secret query(prompt) streaming chunks webhook event edit message live update session CRUD manage state cwd: project dir secrets webhook secret Telegram User sends message Telegram Bot API webhook events n8n Workflow Event routing Inline keyboards FastAPI Session Router Pydantic v2 · Async State Machine IDLE → RUNNING → DONE max 5 concurrent Claude Code SDK async generator yield chunks · asyncio.Queue Redis Session state TTL 24h auto-cleanup HashiCorp Vault Webhook secret · Bot token Chat ID Project Files G:/projects/* path traversal protection

Streaming через async generator

Claude Code SDK отдаёт ответ по частям. Вместо ожидания полного ответа — async generator с yield на каждый chunk. FastAPI собирает chunks в буфер и через asyncio.Queue отправляет обратно в n8n → Telegram, который обновляет сообщение через edit. Пользователь видит, как Claude «печатает» в реальном времени.

Простой await на полный ответ = UX-катастрофа. Claude может думать минуту. Streaming + edit message создаёт ощущение live-общения и позволяет прервать генерацию, если ответ пошёл не туда.

Session State Machine в Redis

Каждая сессия — конечный автомат: IDLE → RUNNING → DONE. Состояние хранится в Redis с TTL 24h. Запрос в RUNNING-сессию ставится в очередь. Session ID — 16-char hex (64-bit entropy). Лимит: max 5 concurrent сессий.

В памяти процесса — потеря состояния при рестарте. Redis переживает деплой, а TTL автоматически чистит зависшие сессии без cron-задач.

Security: defence in depth

Webhook secret в X-Webhook-Secret header — n8n подписывает каждый запрос. Path traversal protection — многоуровневая валидация путей (normalization, whitelist, chroot check). Все входные данные через Pydantic v2 strict-модели. CORS ограничен только n8n origin.

Бот может выполнять команды на сервере через Claude. Один обход path validation = чтение /etc/passwd. Три слоя защиты: нормализация пути, whitelist директорий, финальный chroot check.

Тестирование: 35+ тестов

pytest-asyncio для async-кода. Redis заменён на fakeredis — полная имитация Redis API без реального сервера. Каждый тест изолирован: свой экземпляр fakeredis, нет shared state. Покрыто: API endpoints, session CRUD, webhook retry logic, Telegram message chunking.

Async-код тестировать сложно: event loop, timing, race conditions. pytest-asyncio + fakeredis дают детерминированные тесты без реальных зависимостей. 35 тестов проходят за 2 секунды.
WatchOfWatch — Architecture
350 независимых циферблатов на Canvas API, 6 фаз анимации при 60 FPS — каждый объект интерполирует углы стрелок по собственной траектории
Canvas API Astro Islands TypeScript Kinetic Typography
Animation Engine
ANIMATION PHASE CYCLE (loops forever) PHASE 1 Chaos random angles PHASE 2 Text Pattern interpolate to target PHASE 3 Wave dual sinusoid PHASE 4 Chaos Fisher-Yates reshuffle PHASE 5 Real Time sync Date.now() PHASE 6 Wave dual sinusoid loop Clock Matrix: 50 × 7 = 350 dials Single <canvas> · requestAnimationFrame · 60 FPS × 50 columns × 7 rows = 350 objects · · · · · · · EACH DIAL OBJECT hourAngle · minuteAngle targetH · targetM · phase · t Key Techniques Clockwise-only interpolation Dual sinusoid wind effect Fisher-Yates shuffle O(n) DPR-aware Retina rendering Rendering Pipeline requestAnimationFrame update 1022 angles batch draw 350 dials composite frame 60 FPS

Однонаправленная интерполяция углов

Стрелки всегда вращаются по часовой. Наивный lerp(from, to) выбирает кратчайший путь — стрелка может дёрнуться назад на 350°, что выглядит как баг. Вместо этого: если target < current, интерполяция идёт через target + 2π — стрелка делает полный оборот вперёд.

350 объектов × 2 стрелки = 700 параллельных интерполяции каждый кадр. Все вычисления — чистая математика без DOM, единственный рендеринг — batch draw на Canvas.

Двунаправленная интерполяция визуально хаотична — стрелки мечутся влево-вправо. Однонаправленная создаёт эффект «механизма» — все стрелки крутятся согласованно, как шестерёнки в часах.

Wind Effect: двойная синусоида

«Волна» бежит по матрице как ветер по полю. Два слоя синусоид с разными частотами: крупная волна (длина = ширина матрицы) задаёт общее движение, мелкая рябь (×3 частота, ×0.3 амплитуда) добавляет органичность.

Одна синусоида выглядит механически. Суперпозиция двух — паттерн, который мозг воспринимает как «природное» движение, но не может разложить на составляющие.

Fisher-Yates shuffle

Между фазами порядок обновления циферблатов перемешивается. Fisher-Yates даёт идеально равномерное распределение за O(n) — каждая перестановка равновероятна.

Math.random().sort() имеет bias и O(n log n). При 350 элементах bias заметен визуально — некоторые области «обновляются» раньше. Fisher-Yates это устраняет.

Accessibility и производительность

prefers-reduced-motion: при включённой настройке анимации выключаются, стрелки показывают статичное время. aria-labels на canvas с текстовым описанием. noscript fallback со статичным изображением.

DPR-aware рендеринг: canvas физически в 2-3× больше CSS-размера на Retina. Без этого стрелки размытые.

Pattern Editor (бонус)

909 строк, отдельный WYSIWYG-инструмент. Клик по ячейке → выбор угла для часовой и минутной стрелки. Паттерн экспортируется как JSON-массив и подключается к основному движку.

Позволяет визуально создавать надписи и фигуры, которые движок потом анимирует в фазе «text pattern».

Load Test — API Gateway
Load Test Results