Backend Developer Handbook
Это рабочий справочник для backend-инженеров, пишущих Go-сервисы в KazMaps. Он описывает, как мы пишем код: от установки окружения до ревью pull request’а и отладки проблем в проде. Всё, что здесь описано — это текущий стандарт, а не обсуждение альтернатив.
Handbook предназначен для ежедневного использования. Если ты не знаешь, как оформить новый HTTP-endpoint, добавить миграцию, опубликовать Kafka-событие или отладить застрявший consumer — ответ должен быть здесь.
Структура handbook
content/
├── index.mdx — эта страница
├── onboarding/ — первые шаги: установка, первый PR, локальный стек, ownership
├── conventions/ — правила: layout, Go-стиль, БД, события, HTTP, логирование, тесты,
│ безопасность, ошибки, конфиг, shutdown, observability, коммиты/PR
├── patterns/ — deep-dive по паттернам: outbox, CQRS, idempotent consumer,
│ api composition, retry/CB, saga
├── how-to/ — короткие рецепты («как добавить endpoint», «как добавить миграцию»)
├── checklists/ — чеклисты для автора PR, ревьюера и запуска нового сервиса
├── troubleshooting/ — типовые проблемы и как их чинить
├── services-catalog.mdx — каталог живых сервисов (owner, порт, события, HTTP API)
├── event-catalog.mdx — каталог Kafka-событий (topic, publisher, payload, consumers)
├── architecture-overview.mdx — обзор архитектуры
├── authentication-flow.mdx — end-to-end auth: JWT, HMAC, Gateway → backend
├── quick-ref.mdx — шпаргалка по naming / envelope / метрикам / таймаутам
└── glossary.mdx — глоссарий терминовВ каждой подпапке лежит index.mdx с кратким описанием каждой
страницы и _meta.ts, который управляет порядком и заголовками в
сайдбаре Nextra:
- conventions — индекс conventions.
- patterns — индекс паттернов + когда использовать какой.
- how-to — индекс how-to с группировкой daily-ops / data / security / observability.
- troubleshooting — индекс runbook’ов + правило «сначала сюда, потом в чат».
- checklists — индекс чеклистов + когда использовать какой.
С чего начать новичку
onboarding/01-setup— поставь Go, Docker, golangci-lint, migrate и остальной инструментарий.onboarding/02-first-pr— пройди полный цикл: branch → code → test → PR → merge.architecture-overview— пойми, какая у нас архитектура и какие паттерны используем.onboarding/03-local-stack— подними локально полный стек черезdocker compose.onboarding/04-who-owns-what— узнай, кто владеет каким сервисом, куда писать вопросы.
После онбординга держи открытыми две страницы:
conventions/project-layout— где что лежит в Go-сервисе.checklists/pr-author— перед тем как запросить review.
Как пользоваться
- Правила в
conventions/— обязательны. Если ты отклоняешься, это повод для обсуждения на ревью. - Рецепты в
how-to/— короткие пошаговые инструкции для типовых задач. Начинай с них, когда не уверен, с какого конца подступиться. - Чеклисты в
checklists/— пробегай глазами перед запросом ревью и перед включением прод-трафика на новый сервис. troubleshooting/— загляни сюда прежде чем писать в чат: вероятно, твоя проблема уже описана.
Примеры в handbook берутся из реального кода сервисов user, review,
media, notification. Каждый сервис живёт в отдельном git-репозитории.
Если видишь ссылку вида «в репозитории сервиса user,
internal/handler/router.go» — открой этот путь в клоне соответствующего
сервис-репо и смотри, как сделано.
Карта по задачам
| Задача | Куда смотреть |
|---|---|
| Поставить инструменты, настроить IDE | onboarding/01-setup |
| Открыть первый PR | onboarding/02-first-pr |
| Понять, какая у нас архитектура и какие паттерны | architecture-overview |
| Разобраться в auth-потоке | authentication-flow |
| Разобраться с outbox паттерном | patterns/outbox |
| Разобраться с CQRS | patterns/cqrs |
| Идемпотентный consumer | patterns/idempotent-consumer |
| Композиция данных из нескольких сервисов | patterns/api-composition |
| Retry и circuit breaker для downstream-вызовов | patterns/retry-and-circuit-breaker |
| Поднять локальный стек | onboarding/03-local-stack |
| Понять, где что лежит в сервисе | conventions/project-layout |
| Писать идиоматичный Go-код | conventions/go-style |
| Работать с Postgres и миграциями | conventions/db-pgx |
| Публиковать и потреблять Kafka-события | conventions/events |
| Собрать HTTP-endpoint | conventions/http-api + how-to/add-http-endpoint |
| Настроить логирование | conventions/logging |
| Писать тесты | conventions/testing |
| Обращаться с секретами, валидировать input | conventions/security |
| Обработать ошибки правильно | conventions/error-handling |
| Настроить конфиг сервиса | conventions/configuration |
| Graceful shutdown | conventions/shutdown |
| Инструментовать новый код | conventions/observability |
| Задать SLO и alert-rule | conventions/slo-and-budget |
| Версионировать API | conventions/api-versioning |
| Кэшировать через Redis | conventions/caching |
| Настроить retention данных (soft-delete, TTL, cleanup) | conventions/data-retention |
| Что делать когда Redis недоступен | how-to/handle-redis-outage |
| Добавить Go-dependency | conventions/dependencies + how-to/onboard-new-dependency |
| Wire’ить зависимости в main.go | conventions/dependency-injection |
| Локализовать контент (kk/ru/en) | conventions/i18n |
| Узнать что делает сервис X | services-catalog |
| Найти Kafka-event Y | event-catalog |
| Оформить коммит / PR | conventions/commits-and-prs |
| Добавить миграцию | how-to/add-migration |
| Откатить миграцию в prod | how-to/rollback-migration |
| Добавить событие в Kafka | how-to/add-kafka-event |
| Добавить метрику и алерт | how-to/add-metric-and-alert |
| Запустить новый сервис | how-to/add-new-service + checklists/production-ready |
| Проверить новый HTTP-endpoint перед PR | checklists/new-endpoint |
| Сверить PR как ревьюер | checklists/pr-reviewer |
| Отладить outbox lag | how-to/debug-outbox-lag |
| Провернуть JWT-ключ | how-to/rotate-jwt-key |
| Читать логи в Loki | how-to/read-logs |
| Читать traces в Tempo | how-to/read-traces |
| Профилировать сервис | how-to/profile-service |
| Запустить load test | how-to/load-test |
| Миграция не применяется | troubleshooting/migration-fails |
| Тест висит | troubleshooting/test-hangs |
| Consumer застрял | troubleshooting/kafka-consumer-stuck |
| Consumer в rebalance-loop | troubleshooting/kafka-rebalancing |
| Медленный SQL-запрос | troubleshooting/db-slow-query |
| Memory / goroutine leak | troubleshooting/memory-leak |
| Redis лежит или тормозит | troubleshooting/redis-unavailable |
| Освоиться в Grafana/Prometheus/Loki/Tempo локально | onboarding/05-observability-stack |
| Быстро глянуть формат naming, env, HTTP-кодов | quick-ref |
| Расшифровать термин | glossary |
Как устроены репозитории
Каждый сервис — отдельный git-репозиторий. Это не монорепо — единого корневого репо с сервисами-сиблингами не существует. Когда ты работаешь над сервисом, ты клонируешь именно его репо и работаешь внутри него:
user-service/ — репо: auth + профили
review-service/ — репо: отзывы + реакции
media-service/ — репо: загрузка и хранение медиа
notification-service/ — репо: push/email/sms
backend-docs/ — отдельный репо: этот handbookКаждый сервис — самодостаточный Go-модуль со своим go.mod, Dockerfile,
Makefile, docker-compose.yml и миграциями. У каждого свой жизненный цикл:
отдельные pull request’ы, отдельные релизы, независимый деплой. Сервисы
общаются через HTTP (internal endpoints) и Kafka (асинхронные события).
Общие технические абстракции (pgx-wrapper, shared DTO) пока живут в pkg/
внутри сервис-репо. Когда такой код стабилизируется (зафиксирован API, есть
тесты, определены владельцы) — он выносится в отдельный репозиторий-библиотеку
и подключается через Go-модули. До этого момента допускается копирование
между сервисами; синхронизация — задача владельцев.
Как обновлять handbook
Handbook живёт в отдельном git-репозитории (backend-docs) и обновляется
своими pull request’ами. Полный процесс — в
CONTRIBUTING. Ключевые правила:
- Любое изменение — через pull request. Прямых коммитов в
mainнет. - Требуется approve от lead-инженера backend-команды. Это не бюрократия: handbook определяет, как пишет код вся команда, поэтому правки проходят такой же ревью, как и production-код.
- Меняешь правило — обнови и примеры. Если правишь
conventions/db-pgx.md, убедись, что код-сниппеты остались корректными. - Нашёл расхождение между handbook и реальностью? Открой PR: либо подтяни код под handbook, либо обнови handbook. Расхождение — это баг.
- Формат — MDX с ATX-заголовками (
#,##,###). Строки до 100 символов по возможности. Код-блоки с языковой пометкой (```go,```sql). При добавлении новой страницы зарегистрируй её в ближайшем_meta.ts— иначе она выпадает в конец сайдбара в алфавитном порядке.
Поддержка
- Вопросы по правилам из handbook — пиши в канал backend-команды в мессенджере команды. Если вопрос повторяется — открой PR с уточнением в handbook.
- Вопросы по конкретному сервису — смотри owner’а в
onboarding/04-who-owns-whatи пиши ему напрямую. - Нашёл ошибку в handbook — открывай PR сразу, не жди, пока кто-то ещё наткнётся на то же место.
Где смотреть публичные Go-гайды
Handbook не дублирует общеизвестные Go-гайды. Когда в правилах встречаешь
ссылку на Effective Go или Uber Go Style Guide — открой их и прочитай.
Конкретные проектные отклонения от этих гайдов описаны в
conventions/go-style.
Локальный просмотр документации
Handbook рендерится через Nextra v4 (Next.js 15 + App Router). Для локального просмотра:
make install # pnpm install — Node-зависимости
make dev # pnpm dev — http://localhost:3000 с hot-reloadПеред открытием PR:
make check # check-terms + markdownlint + buildmake check прогоняет forbidden-terms сканер
(scripts/check-terms.sh), markdownlint-cli2 по всем *.md и
*.mdx, и полную сборку pnpm build. Сборка валит PR на
непарсящемся MDX (сломанный JSX, неразрешённый import). Ссылки
дополнительно проверяет make check-links (lychee).
Production-сайт (https://backend-handbook.kazmaps.dev) собирается и
деплоится автоматически через Cloudflare Pages при пуше в main.
Build command в Cloudflare Pages — pnpm install && pnpm build,
output directory — out/ (Next.js static export).