ADR-0021: Stdlib-first runtime для Go-сервисов

Status: accepted Date: 2026-04-17 Deciders: команда проекта

Контекст

В документации оставались незафиксированные технологические развилки:

  • router/mux для HTTP edge;
  • стек для RPC;
  • библиотека для WebSocket;
  • способ dependency injection;
  • правила service-to-service communication внутри docker-compose.

Вариант с gorilla/mux и gorilla/websocket больше не подходит: стек устарел для новых решений, а проекту нужен современный, минималистичный и хорошо поддерживаемый runtime.

Решение

Для новых Go-сервисов фиксируется единый runtime stack:

  • HTTP: net/http + http.ServeMux.
  • RPC: Connect для protobuf-based Connect/gRPC/gRPC-Web.
  • WebSocket: github.com/coder/websocket.
  • DI: runtime DI-контейнер go.uber.org/fx как единый композиционный корень, см. ADR-0030. Самодельные сервис-локаторы, map-based wiring и package-level init(), делающий IO-работу, запрещены.
  • Internal communication: синхронные вызовы между сервисами идут по internal HTTP/Connect endpoint’ам через DNS-имена сервисов в общей docker-compose network.

Дополнительные ограничения:

  • gorilla/mux, gorilla/websocket не используются без отдельного ADR;
  • REST и RPC по возможности живут на одном net/http listener, чтобы не плодить лишние порты и operational surface;
  • host ports не используются для межсервисной коммуникации внутри среды.

Последствия

Плюсы

  • Меньше внешних зависимостей в edge-слое.
  • Прозрачный graph зависимостей и простой unit testing.
  • Один понятный стек для public и internal HTTP API.
  • Одинаковая операционная модель для всех compose-сред.

Минусы

  • Команде нужно соблюдать дисциплину wiring вручную.
  • Некоторые удобства “всё-в-одном” фреймворков отсутствуют и реализуются явно.
  • Переход на Connect требует ранней фиксации .proto контрактов.

Нейтральные последствия

  • WebSocket остаётся отдельным transport-layer, но без legacy-зависимостей.

Рассмотренные альтернативы

gorilla/mux + gorilla/websocket

Отклонено: не соответствует требованию modern stack и создаёт лишний legacy footprint.

chi как базовый router

Отклонено: http.ServeMux покрывает нужный scope проекта, а stdlib-first подход упрощает стек и снижает число зависимостей.

grpc-go + grpc-gateway

Отклонено как default: для проекта удобнее единый Connect stack без отдельного gateway-слоя.

Runtime DI containers (fx, dig, аналоги)

Первоначально (2026-04-17) отклонены из-за опасений «скрытого wiring». Пересмотрено в ADR-0030 (2026-04-20): uber-go/fx принят как единый DI runtime для композиционного корня — ручная сборка не масштабируется на микромонолит с ≥10 BC и усложняет lifecycle/тестовую подмену. Этот раздел ADR-0021 сохраняется как исторический; действующее решение — в ADR-0030.

Ссылки