rhythm-backend/BACKEND_BLUEPRINT.md
Dmitri cb5d273951
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m25s
go
2026-04-19 16:54:12 +02:00

3.3 KiB

Go Backend Blueprint (Iteration Draft)

Chosen Stack

  • Framework: Gin
  • Migrations: Goose (SQL-only)
  • DB Access: SQLC (no ORM), package per bounded context
  • PostgreSQL Driver/Pool: pgx/v5 + pgxpool
  • Logging: Uber Zap (structured logs)
  • Health Probes: liveness/readiness endpoints
  • API Docs: OpenAPI (for frontend TypeScript type generation)
  • Deployment: Docker Compose on self-hosted hardware

Architecture Direction

Layering

  • cmd/api - application entrypoint and dependency wiring
  • internal/http - Gin router, handlers, middleware
  • internal/service - business logic + transaction boundaries
  • internal/db/<context> - SQLC-generated code by bounded context
  • internal/store - shared DB/Tx helpers
  • internal/auth - JWT validation + role guards
  • internal/config - env configuration loading
  • migrations/ - Goose SQL migration files
  • api/openapi/ - OpenAPI spec + generated artifacts

Transaction Strategy

  • Handlers stay thin.
  • Service layer owns DB transactions.
  • SQLC queries are called with either pool or tx using DBTX interfaces.
  • No transaction logic in handlers.

API and Runtime

API Shape

  • REST JSON API
  • Possible future WebSocket support for interactive features
  • Suggested versioning: /api/v1

Health Endpoints

  • GET /health/live - process is alive
  • GET /health/ready - DB ping succeeds (and optionally migration version check)

Logging

  • Zap JSON logs
  • Correlation/request ID in middleware
  • Structured error logging from middleware and service boundaries

Database and Migrations

Goose

  • SQL-only migrations
  • Keep up/down migration scripts
  • Run on startup in non-prod optional, required in CI/CD/deploy step

SQLC

  • Generate one package per bounded context (similar to Spring repository modules)
  • Keep SQL in context directories (query.sql, models.sql style)
  • Service layer composes multiple repositories when needed

Testing Approach (Beginner-Friendly)

  • Unit tests for pure service logic (no DB)
  • Integration tests for SQLC repositories with real Postgres via Docker

Phase 2

  • HTTP handler tests with httptest
  • Auth middleware tests

Phase 3

  • Minimal end-to-end happy path tests

OpenAPI + Frontend Type Generation

  • Keep spec in repo at api/openapi/openapi.yaml
  • Generate frontend TypeScript types from OpenAPI (e.g. openapi-typescript)
  • Optionally serve Swagger UI from backend

Deployment

  • Docker Compose for app + postgres
  • Healthcheck in compose should target readiness endpoint
  • Env-based configuration (.env, .env.example)

Pending Decisions

  1. JWT signing:

    • HS256 shared secret (simple)
    • RS256 keypair (better long-term)
  2. Token model:

    • Access token only
    • Access + refresh token
  3. Initial roles:

    • USER / ADMIN
    • USER / MODERATOR / ADMIN
  4. OpenAPI workflow:

    • Contract-first (spec first)
    • Code-first annotations
  5. CORS policy:

    • Allowed frontend origins in dev/prod
  6. Schema strategy:

    • Single schema (public) confirmation
  7. Initial bounded contexts:

    • e.g. auth, users, rooms (or your domain names)

Iteration Notes

  • This file is intentionally a working draft.
  • We will refine decisions and turn this into a concrete implementation checklist.