A production-ready, enterprise-grade Go microservice boilerplate featuring distributed tracing, health checks, structured logging, metrics, and Docker support.
- RESTful API with Gin framework
- Clean Architecture with domain-driven design
- PostgreSQL database with connection pooling
- Database Migrations with golang-migrate
- Repository Pattern for data access
- Service Layer for business logic
- Distributed Tracing with OpenTelemetry and Jaeger
- Structured Logging with Zap
- Prometheus Metrics for monitoring
- Health Check Endpoints (liveness and readiness probes)
- Graceful Shutdown handling
- Docker Support with multi-stage builds
- Docker Compose for local development
- CI/CD Pipeline with GitHub Actions
- Request ID Tracking for correlation
- CORS Middleware for cross-origin requests
- Metrics Collection for performance monitoring
- Makefile for common tasks
- Hot Reload support (via air or similar tools)
- Comprehensive Tests with mocks
- Code Quality with golangci-lint
- Environment Configuration with Viper
.
├── cmd/
│ └── server/
│ └── main.go # Application entry point
├── internal/
│ ├── api/
│ │ ├── handlers/ # HTTP request handlers
│ │ │ ├── health.go
│ │ │ └── user.go
│ │ └── router.go # Route definitions
│ ├── config/
│ │ └── config.go # Configuration management
│ ├── domain/
│ │ ├── models/ # Business models
│ │ │ └── user.go
│ │ ├── repository/ # Repository interfaces
│ │ │ └── user_repository.go
│ │ └── service/ # Business logic
│ │ ├── user_service.go
│ │ └── user_service_test.go
│ ├── infrastructure/
│ │ ├── database/ # Database layer
│ │ │ ├── postgres.go
│ │ │ ├── migrations.go
│ │ │ └── user_repository_impl.go
│ │ ├── logging/ # Logging setup
│ │ │ └── logger.go
│ │ ├── metrics/ # Prometheus metrics
│ │ │ └── metrics.go
│ │ └── tracing/ # Distributed tracing
│ │ └── tracing.go
│ └── middleware/ # HTTP middleware
│ ├── cors.go
│ ├── logging.go
│ ├── metrics.go
│ └── request_id.go
├── migrations/ # Database migrations
│ ├── 000001_create_users_table.up.sql
│ └── 000001_create_users_table.down.sql
├── .github/
│ └── workflows/
│ └── ci.yml # GitHub Actions CI/CD
├── config.yaml # Default configuration
├── docker-compose.yml # Local development stack
├── Dockerfile # Multi-stage Docker build
├── Makefile # Build automation
├── prometheus.yml # Prometheus configuration
├── .env.example # Environment variables template
├── .gitignore
├── go.mod
├── go.sum
└── README.md
- Go 1.21 or higher
- Docker and Docker Compose
- PostgreSQL 15+ (for local development without Docker)
- Make (optional, for using Makefile commands)
git clone https://github.com/codeforgood-org/go-microservice-boilerplate.git
cd go-microservice-boilerplatecp .env.example .env
# Edit .env with your configuration# Start all services (app, postgres, jaeger, prometheus, grafana)
make docker-up
# Or manually
docker-compose up -dThis will start:
- API Server on http://localhost:8080
- Jaeger UI on http://localhost:16686
- Prometheus on http://localhost:9090
- Grafana on http://localhost:3000
- PostgreSQL on localhost:5432
# Check health
curl http://localhost:8080/health
# Check readiness
curl http://localhost:8080/ready
# Check metrics
curl http://localhost:8080/metrics# Install dependencies
make deps
# Run database migrations
# (Ensure PostgreSQL is running)
make migrate-up
# Run the application
make run# Build binary
make build
# The binary will be in ./bin/server
./bin/server# Run all tests
make test
# Run tests with coverage
make coverage
# View coverage report
open coverage.html# Format code
make fmt
# Run linter
make lint
# Run go vet
make vet
# Run all checks
make allGET /health- Liveness probe (always returns 200 if app is running)GET /ready- Readiness probe (checks database connectivity)GET /metrics- Prometheus metrics endpoint
POST /api/v1/users- Create a new userGET /api/v1/users- List users (with pagination)GET /api/v1/users/:id- Get user by IDPUT /api/v1/users/:id- Update userDELETE /api/v1/users/:id- Delete user
curl -X POST http://localhost:8080/api/v1/users \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"username": "johndoe",
"full_name": "John Doe"
}'curl "http://localhost:8080/api/v1/users?limit=10&offset=0"curl http://localhost:8080/api/v1/users/{user-id}Configuration can be provided via:
config.yamlfile- Environment variables (override config file)
See .env.example for all available configuration options.
Key variables:
ENVIRONMENT- Environment (development, production)SERVER_PORT- HTTP server portDATABASE_HOST- PostgreSQL hostDATABASE_PORT- PostgreSQL portTRACING_ENABLED- Enable/disable distributed tracingTRACING_JAEGER_URL- Jaeger collector URLLOGGING_LEVEL- Log level (debug, info, warn, error)
make migrate-create NAME=add_users_tableThis creates two files:
migrations/{timestamp}_add_users_table.up.sqlmigrations/{timestamp}_add_users_table.down.sql
Migrations run automatically on application startup.
For manual control, you can use golang-migrate:
# Install migrate tool
make install-tools
# Run migrations
migrate -path migrations -database "postgres://user:pass@localhost:5432/dbname?sslmode=disable" up
# Rollback
migrate -path migrations -database "postgres://user:pass@localhost:5432/dbname?sslmode=disable" down- Access Jaeger UI at http://localhost:16686
- Select service
go-microservice - View traces and spans for all requests
- Access Prometheus at http://localhost:9090
- Available metrics:
http_requests_total- Total HTTP requestshttp_request_duration_seconds- Request duration histogramdatabase_queries_total- Total database queriesdatabase_query_duration_seconds- Query duration histogramdatabase_active_connections- Active database connections
- Access Grafana at http://localhost:3000
- Default credentials: admin/admin
- Prometheus is pre-configured as a data source
- Create dashboards for your metrics
Logs are output in JSON format (production) or console format (development).
Each log entry includes:
- Timestamp
- Log level
- Request ID (for request correlation)
- Message
- Additional context fields
make docker-build# Start all services
make docker-up
# View logs
make docker-logs
# Stop all services
make docker-down
# Restart services
make docker-restartThe project includes a GitHub Actions workflow that:
- Runs linting (golangci-lint)
- Executes tests with coverage
- Builds the application
- Builds Docker image
- Runs security scans (Trivy)
The workflow runs on:
- Push to
mainordevelopbranches - Pull requests to
mainordevelopbranches
make testmake coverage
# Opens coverage.html in your browser- Unit tests for services use mock repositories
- Handler tests use
httptestpackage - See
internal/domain/service/user_service_test.gofor examples
make help # Show all available commands
make build # Build the application
make run # Run the application
make test # Run tests
make coverage # Generate coverage report
make lint # Run linter
make fmt # Format code
make clean # Clean build artifacts
make docker-build # Build Docker image
make docker-up # Start Docker Compose services
make docker-down # Stop Docker Compose services-
Domain Layer (
internal/domain/)- Business models
- Repository interfaces
- Business logic (services)
-
Infrastructure Layer (
internal/infrastructure/)- Database implementations
- External service integrations
- Logging, metrics, tracing
-
API Layer (
internal/api/)- HTTP handlers
- Request/response models
- Route definitions
-
Application Layer (
cmd/server/)- Application entry point
- Dependency injection
- Graceful shutdown
- Repository Pattern - Abstract data access
- Dependency Injection - Loose coupling
- Middleware Pattern - Cross-cutting concerns
- Factory Pattern - Object creation
Example Kubernetes manifests:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-microservice
spec:
replicas: 3
selector:
matchLabels:
app: go-microservice
template:
metadata:
labels:
app: go-microservice
spec:
containers:
- name: app
image: go-microservice:latest
ports:
- containerPort: 8080
env:
- name: ENVIRONMENT
value: "production"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5- Set
ENVIRONMENT=production - Use secure database credentials
- Configure appropriate connection pool sizes
- Set appropriate timeouts
- Enable HTTPS/TLS
- Configure appropriate log levels
- Input validation on all API endpoints
- SQL injection prevention (parameterized queries)
- CORS configuration
- Request size limits
- Rate limiting (can be added via middleware)
- Secrets management (use environment variables, not hardcoded)
- Regular dependency updates
- Security scanning in CI/CD
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License.
For issues and questions:
- Open an issue on GitHub
- Check existing documentation
- Review the code examples
- Add authentication/authorization (JWT)
- Add rate limiting middleware
- Add caching layer (Redis)
- Add message queue support (RabbitMQ/Kafka)
- Add API documentation (Swagger/OpenAPI)
- Add more comprehensive examples
- Add performance benchmarks
- Add load testing examples
- Gin Web Framework
- OpenTelemetry
- Prometheus
- Jaeger
- Zap Logger
- Viper Configuration
Built with ❤️ for production-ready Go microservices