This is a professional template for building Go applications following the Modulith pattern. It's designed to be scalable, maintainable, and easy to maintain, allowing evolution from a monolith to microservices without friction.
- ๐๏ธ Modular Architecture: Code organized by domains with decoupling through internal events.
- ๐ฆ Registry Pattern: Manual, explicit dependency injection without magic for maximum control.
- ๐ gRPC & Protobuf: Typed and efficient communication with automatic code generation via
buf. - ๐๏ธ SQLC & Migrations: Type-safe data access and schema management with
golang-migrate. - โ๏ธ Flexible Configuration: Configuration system with precedence hierarchy (YAML > .env > system ENV vars > defaults) and source logging.
- ๐ Hot Reload: Smooth development with Air monitoring changes in code, configuration (
.env, YAML) and resources. - ๐ WebSocket Real-Time: Bidirectional communication integrated with the event bus for real-time notifications.
- ๐ท Worker Process: Background process for asynchronous tasks, event consumers, and scheduled jobs.
- ๐ Secrets Management: Abstraction for secret management (env vars, Vault, AWS Secrets Manager).
- ๐ Complete Observability: Local stack with Jaeger, Prometheus, and Grafana for development and debugging.
- ๐ Optional GraphQL: Optional support with gqlgen for flexible and frontend-friendly APIs (subscriptions included).
- ๐ง Notification System: Templates + extensible providers (SendGrid, Twilio, AWS SES/SNS).
- ๐ Complete Auth: Passwordless login, sessions, refresh tokens, revocation, and profile management.
- ๐ OAuth/Social Login: Authentication with Google, Facebook, GitHub, Apple, Microsoft, and Twitter/X.
- ๐งช Mocking with gomock: Automatic generation of type-safe mocks for efficient unit testing.
- ๐งช Test Utilities: Comprehensive testing utilities (
internal/testutil) for integration tests, gRPC servers, event bus, and test registries. - ๐ก๏ธ Observability: Native integration with OpenTelemetry (Tracing & Metrics), Prometheus, and Health Checks with context handling.
- โก Error Handling: Domain error system with automatic mapping to gRPC codes.
- ๐ก Telemetry Helpers: Integrated helpers for consistent tracing across all modules.
- ๐ฏ Typed Events: Typed constants for events with autocomplete and typo prevention.
- ๐ Multi-Module Migrations: Automatic discovery and execution of migrations per module.
- ๐ RBAC Built-in: Authorization helpers for permissions, roles, and ownership.
- โด๏ธ Cloud Ready: Multi-stage Dockerfile and flexible Helm Charts for Kubernetes (supports monolith and independent modules).
- ๐ IaC with OpenTofu: Reproducible base infrastructure (VPC, EKS, RDS) managed with OpenTofu and Terragrunt.
- ๐ค CI/CD: GitHub Actions pipelines for automatic validation.
- Go 1.24+
- Docker & Docker Compose
- Development tools:
sqlcbufmigrateairgolangci-lint
The fastest way to get started is using the automated quickstart script:
make quickstartThis will:
- Validate your environment setup
- Install missing development tools
- Start Docker infrastructure
- Run database migrations
- Optionally run seed data
๐ก Tip: For a minimal setup (database + Redis only), use
make docker-up-minimal.
Check that all prerequisites are installed:
make validate-setupmake install-depsThe template includes a complete observability stack for local development:
make docker-upThis starts:
- PostgreSQL: Main database
- Redis: Cache and session storage
- Jaeger: Distributed tracing (UI at http://localhost:16686)
- Prometheus: Metrics and alerts (UI at http://localhost:9090)
- Grafana: Visualization dashboards (UI at http://localhost:3000, user:
admin, password:admin)
๐ก Tip: To start only the database and Redis, use
make docker-up-minimal.
The project supports multiple configuration sources with clear precedence:
PORT(standard 12-factor variable): Highest priority, compatible with Heroku, Cloud Run, Railway, etc.- YAML (
configs/server.yaml): High priority, ideal for environment-specific configurations .env: Overrides system environment variables- System environment variables: Base values
- Defaults: Hardcoded values in
config.go
Priority: PORT > YAML > .env > system ENV vars > defaults
Edit configs/server.yaml with your configuration values (DB connection, JWT secret, OAuth, etc.).
On startup, you'll see a log showing the source of each configuration variable.
๐ก OAuth Tip: To enable OAuth providers (Google, GitHub, etc.), configure credentials in
configs/server.yamlor in your.envfile. See complete OAuth guide.
make devTo run a specific module with hot reload:
make dev-module authTo run the worker process (background tasks):
make dev-worker
# or
make build-worker && ./bin/worker๐ก Tip: Air automatically monitors changes in
.go,.yaml,.env,.proto,.sqland configuration files, restarting the server instantly.
The template includes an abstraction for secrets management that allows using different providers:
- Development: Environment variables (
EnvProviderimplementation) - Production: HashiCorp Vault, AWS Secrets Manager, etc. (extensible)
See environment variables documentation for more details.
The template follows the stateless processes principle:
- โ No local state: No temporary files are written or state stored on disk
- โ State in external services: Sessions in PostgreSQL, optional cache in Redis
- โ Horizontal scaling: Any instance can handle any request
โ ๏ธ WebSocket: Requires sticky sessions for scaling (see documentation)
See complete documentation: docs/MODULITH_ARCHITECTURE.md (section 20: Stateless Processes)
The server exposes health check endpoints for integration with orchestrators (Kubernetes, Docker Swarm, etc.):
/livez: Liveness probe - always returns 200 if the process is alive/readyz: Readiness probe - checks dependencies (DB, modules, event bus, WebSocket)/healthz: Legacy endpoint (backward compatibility, same as/livez)/healthz/ws: WebSocket connection status (active connections and connected users)
The /readyz endpoint returns detailed JSON with the status of each dependency:
{
"status": "ready",
"checks": {
"modules": "healthy",
"database": "healthy",
"event_bus": "healthy",
"websocket": "healthy"
}
}If any dependency is unhealthy, the endpoint returns 503 Service Unavailable.
The template includes an administrative task system for maintenance operations:
Available tasks:
cleanup-sessions: Cleans expired user sessionscleanup-magic-codes: Cleans expired magic codes
Usage:
# Run an administrative task
make admin TASK=cleanup-sessions
# Or directly with the binary
./bin/server admin cleanup-sessions
./bin/server admin cleanup-magic-codes
# List available tasks
./bin/server adminAdministrative tasks run as independent commands and are useful for:
- Periodic cleanup of expired data
- Database maintenance
- Data migration operations
- Audit tasks
- Architecture Guide - โญ Complete architecture, patterns, error handling, telemetry, typed events, RBAC, testing and more
- Module Communication - โญ How communication works in Modulith vs Microservices, gRPC in-process vs network, event bus
- 12-Factor App Compliance - Complete guide to 12-factor app methodology compliance
- OAuth/Social Login - Integration with Google, Facebook, GitHub, Apple, Microsoft, Twitter
- Notification System - Templates, providers (SendGrid, Twilio, SES) and composite notifier
- Real-Time WebSocket - Bidirectional communication, event bus and JWT authentication
- GraphQL Integration - Optional setup with gqlgen, schema per module and subscriptions
- Deployment & IaC - OpenTofu, Helm Charts, deployment strategies and testing
- Frontend Proposal - Go Templates + HTMX with WebSocket/GraphQL
- Deployment Guide - Complete Kubernetes deployment guide
- Helm Chart Documentation - Detailed Helm chart documentation
The project automatically generates OpenAPI/Swagger documentation:
- Location:
gen/openapiv2/proto/(generated withmake proto) - Format: JSON compatible with Swagger UI
- Usage: Import
.swagger.jsonfiles into Swagger Editor or any compatible tool
Example for the auth module:
# Generate documentation
make proto
# View the API
open gen/openapiv2/proto/auth/v1/auth.swagger.jsonmake proto: Generates gRPC code from.protofiles (includes OpenAPI/Swagger ingen/openapiv2/).make sqlc: Generates Type-safe code for SQL queries.
make build: Compiles the monolith binary inbin/server.make build-module MODULE_NAME: Compiles the binary for a specific module (e.g.:make build-module auth).make build-all: Compiles all binaries (server + all modules).make clean: Removes all build artifacts (bin/directory).
make quickstart: Automated setup process (installs deps, starts docker, runs migrations).make validate-setup: Validates development environment setup (prerequisites, tools, ports).make doctor: Comprehensive development environment diagnostics (containers, connectivity, configuration).
make docker-up: Starts all infrastructure services (PostgreSQL, Redis, Jaeger, Prometheus, Grafana).make docker-up-minimal: Starts minimal services (PostgreSQL + Redis only) for faster startup.make docker-down: Stops Docker containers.make docker-build: Builds the server Docker image (modulith-server:latest).make docker-build-module MODULE_NAME: Builds the Docker image for a specific module (e.g.:make docker-build-module auth).
make lint: Runs the strict linter (MANDATORY after changes to.gofiles).make test: Runs all unit tests.make test-unit: Runs unit tests with mocks (fast, no DB).make test-coverage: Runs tests and generates HTML coverage report.make coverage-report: Shows detailed coverage report in terminal.make coverage-html: Opens coverage report in browser.make generate-mocks: Generates interface mocks for testing.make install-mocks: Installs gomock for mock generation.
make dev: Runs the monolith server with hot reload.make dev-module MODULE_NAME: Runs a specific module with hot reload (e.g.:make dev-module auth).make new-module MODULE_NAME: Creates boilerplate for a new functional module with automatic configuration (generates structure +.air.{MODULE_NAME}.toml).
make migrate-up/make migrate: Runs migrations for all modules (the modulith discovers them automatically).make migrate-down MODULE=auth: Reverts the last migration for a specific module.make migrate-create MODULE=auth NAME=add_users: Creates a new migration for a specific module.make db-down:โ ๏ธ Deletes all database tables (destructive).make db-reset:โ ๏ธ Deletes everything and runs all migrations (equivalent todb-down+migrate-up).
Note: Migrations run automatically when you start the server. The modulith discovers and applies migrations for all registered modules.
make admin TASK=cleanup-sessions: Runs administrative task to clean expired sessions.make admin TASK=cleanup-magic-codes: Runs administrative task to clean expired magic codes../bin/server admin <task_name>: Runs an administrative task directly.
Note: Administrative tasks run as independent commands. You can list available tasks by running ./bin/server admin without arguments.
make graphql-init: Adds optional GraphQL support using gqlgen and automatically generates code (one command does everything).make graphql-generate-all: Generates GraphQL code from schemas for all modules.make graphql-generate-module MODULE_NAME=<name>: Generates GraphQL code for a specific module (auto-generates schema from proto if missing).make graphql-from-proto: Generates GraphQL schemas from OpenAPI/Swagger definitions for all modules.make graphql-validate: Validates GraphQL schema.
After modifying .go files:
- Run
make lintand fix all errors (0 issues). - Run
make testto verify you didn't break anything. - NEVER modify
.golangci.yamlto ignore errors - implement proper fixes.
If you encounter issues with your development environment:
- Run diagnostics:
make doctor- Comprehensive health check of your environment - Validate setup:
make validate-setup- Check prerequisites and configuration - Check containers:
docker-compose ps- Verify Docker containers are running - View logs:
docker-compose logs [service]- Check service logs - Reset database:
make db-reset- Drop and recreate database (destructive)
Common issues:
- Port conflicts: Use
make doctorto identify which ports are in use - Docker not running: Start Docker Desktop or docker service
- Database connection errors: Ensure containers are running with
make docker-up - Missing tools: Run
make install-depsto install all development tools
Made with โค๏ธ for developers seeking operational excellence.