Skip to content

codeforgood-org/go-microservice-boilerplate

Repository files navigation

Go Microservice Boilerplate

A production-ready, enterprise-grade Go microservice boilerplate featuring distributed tracing, health checks, structured logging, metrics, and Docker support.

Features

Core Features

  • 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

Observability

  • Distributed Tracing with OpenTelemetry and Jaeger
  • Structured Logging with Zap
  • Prometheus Metrics for monitoring
  • Health Check Endpoints (liveness and readiness probes)

Production Ready

  • 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

Developer Experience

  • 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

Project Structure

.
├── 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

Prerequisites

  • Go 1.21 or higher
  • Docker and Docker Compose
  • PostgreSQL 15+ (for local development without Docker)
  • Make (optional, for using Makefile commands)

Quick Start

1. Clone the Repository

git clone https://github.com/codeforgood-org/go-microservice-boilerplate.git
cd go-microservice-boilerplate

2. Set Up Environment Variables

cp .env.example .env
# Edit .env with your configuration

3. Start with Docker Compose

# Start all services (app, postgres, jaeger, prometheus, grafana)
make docker-up

# Or manually
docker-compose up -d

This will start:

4. Verify the Service

# Check health
curl http://localhost:8080/health

# Check readiness
curl http://localhost:8080/ready

# Check metrics
curl http://localhost:8080/metrics

Development

Run Locally (without Docker)

# Install dependencies
make deps

# Run database migrations
# (Ensure PostgreSQL is running)
make migrate-up

# Run the application
make run

Build the Application

# Build binary
make build

# The binary will be in ./bin/server
./bin/server

Run Tests

# Run all tests
make test

# Run tests with coverage
make coverage

# View coverage report
open coverage.html

Code Quality

# Format code
make fmt

# Run linter
make lint

# Run go vet
make vet

# Run all checks
make all

API Endpoints

Health Checks

  • GET /health - Liveness probe (always returns 200 if app is running)
  • GET /ready - Readiness probe (checks database connectivity)
  • GET /metrics - Prometheus metrics endpoint

User API (v1)

  • POST /api/v1/users - Create a new user
  • GET /api/v1/users - List users (with pagination)
  • GET /api/v1/users/:id - Get user by ID
  • PUT /api/v1/users/:id - Update user
  • DELETE /api/v1/users/:id - Delete user

Example Requests

Create 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"
  }'

List Users

curl "http://localhost:8080/api/v1/users?limit=10&offset=0"

Get User by ID

curl http://localhost:8080/api/v1/users/{user-id}

Configuration

Configuration can be provided via:

  1. config.yaml file
  2. Environment variables (override config file)

Environment Variables

See .env.example for all available configuration options.

Key variables:

  • ENVIRONMENT - Environment (development, production)
  • SERVER_PORT - HTTP server port
  • DATABASE_HOST - PostgreSQL host
  • DATABASE_PORT - PostgreSQL port
  • TRACING_ENABLED - Enable/disable distributed tracing
  • TRACING_JAEGER_URL - Jaeger collector URL
  • LOGGING_LEVEL - Log level (debug, info, warn, error)

Database Migrations

Create a New Migration

make migrate-create NAME=add_users_table

This creates two files:

  • migrations/{timestamp}_add_users_table.up.sql
  • migrations/{timestamp}_add_users_table.down.sql

Run Migrations

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

Monitoring and Observability

Distributed Tracing with Jaeger

  1. Access Jaeger UI at http://localhost:16686
  2. Select service go-microservice
  3. View traces and spans for all requests

Metrics with Prometheus

  1. Access Prometheus at http://localhost:9090
  2. Available metrics:
    • http_requests_total - Total HTTP requests
    • http_request_duration_seconds - Request duration histogram
    • database_queries_total - Total database queries
    • database_query_duration_seconds - Query duration histogram
    • database_active_connections - Active database connections

Visualization with Grafana

  1. Access Grafana at http://localhost:3000
  2. Default credentials: admin/admin
  3. Prometheus is pre-configured as a data source
  4. Create dashboards for your metrics

Structured Logging

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

Docker

Build Docker Image

make docker-build

Run with Docker Compose

# Start all services
make docker-up

# View logs
make docker-logs

# Stop all services
make docker-down

# Restart services
make docker-restart

CI/CD

The 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 main or develop branches
  • Pull requests to main or develop branches

Testing

Unit Tests

make test

Test Coverage

make coverage
# Opens coverage.html in your browser

Writing Tests

  • Unit tests for services use mock repositories
  • Handler tests use httptest package
  • See internal/domain/service/user_service_test.go for examples

Makefile Commands

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

Architecture

Clean Architecture Layers

  1. Domain Layer (internal/domain/)

    • Business models
    • Repository interfaces
    • Business logic (services)
  2. Infrastructure Layer (internal/infrastructure/)

    • Database implementations
    • External service integrations
    • Logging, metrics, tracing
  3. API Layer (internal/api/)

    • HTTP handlers
    • Request/response models
    • Route definitions
  4. Application Layer (cmd/server/)

    • Application entry point
    • Dependency injection
    • Graceful shutdown

Design Patterns

  • Repository Pattern - Abstract data access
  • Dependency Injection - Loose coupling
  • Middleware Pattern - Cross-cutting concerns
  • Factory Pattern - Object creation

Production Deployment

Kubernetes

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

Environment Variables for Production

  • Set ENVIRONMENT=production
  • Use secure database credentials
  • Configure appropriate connection pool sizes
  • Set appropriate timeouts
  • Enable HTTPS/TLS
  • Configure appropriate log levels

Security Best Practices

  • 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

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License.

Support

For issues and questions:

  • Open an issue on GitHub
  • Check existing documentation
  • Review the code examples

Roadmap

  • 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

Acknowledgments

  • Gin Web Framework
  • OpenTelemetry
  • Prometheus
  • Jaeger
  • Zap Logger
  • Viper Configuration

Built with ❤️ for production-ready Go microservices

About

No description, website, or topics provided.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •