Clean Architecture + CQRS + DDD + UoW (using Golang/Gin) — Production-ready booking system template with idempotent APIs & race-safe reservations
- Clean Architecture
- True Idempotency JWT + RBAC
git clone <this-repo>
cd gin-clean-starter
mise install && mise run install # Install tools & dependencies
mise run up # Start PostgreSQL
mise run migrate:up # Apply schemamise run migrate:up # Apply migrations
mise run migrate:status # Check status
mise run migrate:down # Rollbackmise run migrate:hash # Fix checksum errors
mise run migrate:up # Then applymise run sqlc:gen # Regenerate type-safe DB code| Task | Command | Description |
|---|---|---|
| Test | mise run test-all |
Unit + E2E tests |
| Lint | mise run lint:fix |
Auto-fix code issues |
| Build | mise run build |
Docker images |
All available commands
# Environment
mise run up # Start services
mise run down # Stop services
mise run logs # View logs
# Code quality
mise run lint # Check issues
mise run fmt # Format code
mise run sql:format # Format SQL
# Testing
mise run test-unit # Unit tests only
mise run test-e2e # E2E tests only
mise run test-clean # Clean test cacheAll endpoints require auth (except /auth/login). Uses Idempotency-Key header for safe retries.
# Login
curl -X POST localhost:8888/auth/login \
-d '{"email":"[email protected]","password":"password123"}'
# Create reservation (idempotent)
curl -X POST localhost:8888/reservations \
-H "Authorization: Bearer <token>" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"resource_id":"...","start_time":"2024-01-01T10:00:00Z",...}'Swagger docs: http://localhost:8888/swagger/ (debug mode)
- Cursor format: keyset pagination uses Base64URL cursor
v1:<created_at_unix_micro>-<uuid>encoded as Base64URL. Invalid cursor → 400. - Errors: map infrastructure/usecase errors to HTTP codes consistently — 400 (invalid input), 401 (unauthorized), 403 (forbidden), 404 (not found), 409 (conflict), 500 (internal error).
internal/
├── domain/ # Pure business logic (no dependencies)
├── usecase/ # Application services + interfaces
├── handler/ # HTTP layer (Gin routes + middleware)
├── infra/ # Database, external services
└── pkg/ # Shared utilities
Key Patterns:
- CQRS — Separate read/write models for performance
- Repository — Clean data access abstraction
- DI — Uber FX for dependency injection
- Value Objects — Type-safe domain primitives
Built for booking/reservation systems where race conditions and data consistency are critical. Includes real-world patterns like:
- Time slot conflicts → Prevented at DB level with EXCLUDE constraints
- Request duplication → Handled with proper idempotency (not just dedup)
- Domain validation → Clean separation from HTTP concerns
- Role-based access → JWT with viewer/operator/admin levels