Production-ready Go REST & gRPC API starter template with JWT authentication, Kubernetes deployment, Clean Architecture, and a Rust CLI client.
Category
Features
Authentication
JWT with refresh tokens, bcrypt password hashing, RBAC (Admin/User/Viewer)
Architecture
Clean Architecture (Handler → Service → Repository), Dependency Injection
API
REST (Echo v4) + gRPC with streaming, OpenAPI 3.1 specification
Resilience
Circuit breaker, retry with exponential backoff, rate limiting, graceful shutdown
Observability
OpenTelemetry tracing (Jaeger), Prometheus metrics, structured logging (slog), audit logs
Infrastructure
Docker, Kubernetes manifests with Kustomize (dev/prod), GitHub Actions CI/CD
Developer Tools
Rust CLI client, Dev Container, Taskfile, pre-commit hooks, sqlc
Go Patterns
Generics (Result/Option types), Worker Pool, Context utilities, Type-safe errors
┌─────────────────────────────────────────────────────────────────────────────┐
│ Transport Layer │
│ ┌───────────────────────────────┐ ┌───────────────────────────────┐ │
│ │ REST (Echo) │ │ gRPC (grpc-go) │ │
│ │ Port 8080 │ │ Port 9090 │ │
│ │ /api/v1/todos, /health │ │ TodoService (streaming) │ │
│ └───────────────────────────────┘ └───────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ Middleware Chain │
│ RequestID → Logger → Recovery → RateLimiter → Auth → RBAC │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ Handler Layer │
│ Request validation, response formatting, error mapping to HTTP/gRPC codes │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ Service Layer │
│ Business logic, JWT generation, password hashing, authorization checks │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ Repository Layer │
│ Data access interfaces, PostgreSQL implementation (sqlc generated) │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ PostgreSQL │
│ users (id, email, password_hash, role) ←──→ todos (id, user_id, title...) │
└─────────────────────────────────────────────────────────────────────────────┘
go-api-starter/
├── cmd/server/ # Application entry point with graceful shutdown
├── internal/
│ ├── config/ # Configuration management (env, validation)
│ ├── handler/ # HTTP handlers (REST controllers)
│ ├── grpc/ # gRPC server and service implementations
│ ├── middleware/ # Custom middleware (auth, logging, rate limit)
│ ├── model/ # Domain models
│ ├── repository/ # Data access layer (interfaces + implementations)
│ └── service/ # Business logic layer
├── pkg/ # Reusable packages (see below)
│ ├── apperrors/ # Custom error types with Is/As support
│ ├── cache/ # Generic in-memory cache with TTL/LRU
│ ├── circuitbreaker/ # Circuit breaker pattern
│ ├── generic/ # Result/Option types, functional helpers
│ ├── healthcheck/ # K8s-ready health check system
│ ├── metrics/ # Prometheus metrics
│ ├── rbac/ # Role-based access control
│ ├── resilience/ # Retry, timeout, fallback patterns
│ ├── retry/ # Exponential backoff with jitter
│ ├── token/ # JWT token generation/validation
│ ├── tracing/ # OpenTelemetry integration
│ └── workerpool/ # Concurrent task processing
├── api/grpc/ # Protocol Buffers definitions
├── gen/go/ # Generated gRPC code (buf)
├── deploy/
│ └── k8s/ # Kubernetes manifests
│ ├── base/ # Base manifests (Deployment, Service, HPA, etc.)
│ └── overlays/ # Environment-specific (development, production)
├── tools/
│ └── todo-cli/ # Rust CLI client for the API
├── db/
│ ├── migrations/ # SQL migrations
│ └── queries/ # sqlc query definitions
├── docs/
│ ├── adr/ # Architecture Decision Records
│ └── openapi.yaml # OpenAPI 3.1 specification
└── .github/workflows/ # CI/CD pipelines
Go 1.22+
Docker & Docker Compose
(Optional) Task for development commands
Option 1: Docker Compose (Recommended)
# Clone and start all services
git clone https://github.com/hassan123789/go-api-starter.git
cd go-api-starter
docker-compose up -d
# API available at http://localhost:8080
# gRPC available at localhost:9090
Option 2: Local Development
# Clone repository
git clone https://github.com/hassan123789/go-api-starter.git
cd go-api-starter
# Setup environment
cp .env.example .env
# Start PostgreSQL
docker-compose up -d postgres
# Run migrations
export DATABASE_URL=" postgres://postgres:postgres@localhost:5432/go_api_starter?sslmode=disable"
task migrate # or: make migrate
# Start server (with hot reload)
task run # or: make run
Option 3: Dev Container (VS Code)
Open the project in VS Code
Click "Reopen in Container" when prompted
All tools and dependencies are pre-configured
Method
Endpoint
Description
Auth
GET
/health
Full health check with dependencies
❌
GET
/livez
Kubernetes liveness probe
❌
GET
/readyz
Kubernetes readiness probe
❌
GET
/metrics
Prometheus metrics
❌
POST
/api/v1/users
Register new user
❌
POST
/api/v1/auth/login
Login, returns JWT
❌
POST
/api/v1/auth/refresh
Refresh access token
✅
GET
/api/v1/todos
List todos (paginated)
✅
POST
/api/v1/todos
Create todo
✅
GET
/api/v1/todos/:id
Get todo by ID
✅
PUT
/api/v1/todos/:id
Update todo
✅
DELETE
/api/v1/todos/:id
Delete todo
✅
service TodoService {
rpc CreateTodo (CreateTodoRequest ) returns (Todo );
rpc GetTodo (GetTodoRequest ) returns (Todo );
rpc ListTodos (ListTodosRequest ) returns (ListTodosResponse );
rpc UpdateTodo (UpdateTodoRequest ) returns (Todo );
rpc DeleteTodo (DeleteTodoRequest ) returns (google.protobuf.Empty );
rpc StreamTodos (StreamTodosRequest ) returns (stream TodoEvent ); // Real-time updates
}
# Register a user
curl -X POST http://localhost:8080/api/v1/users \
-H " Content-Type: application/json" \
-d ' {"email": "user@example.com", "password": "securepass123"}'
# Login
TOKEN=$( curl -s -X POST http://localhost:8080/api/v1/auth/login \
-H " Content-Type: application/json" \
-d ' {"email": "user@example.com", "password": "securepass123"}' | jq -r ' .token' )
# Create a todo
curl -X POST http://localhost:8080/api/v1/todos \
-H " Content-Type: application/json" \
-H " Authorization: Bearer $TOKEN " \
-d ' {"title": "Learn Go patterns", "description": "Study clean architecture"}'
# List todos
curl http://localhost:8080/api/v1/todos \
-H " Authorization: Bearer $TOKEN "
A native CLI tool for interacting with the API:
# Build the CLI
cd tools/todo-cli
cargo build --release
# Configure API endpoint
./target/release/todo-cli config set-url http://localhost:8080
# Authenticate
./target/release/todo-cli auth login
# Manage todos
./target/release/todo-cli list
./target/release/todo-cli create --title " New task" --description " Details"
./target/release/todo-cli done 1
./target/release/todo-cli delete 1
# JSON output for scripting
./target/release/todo-cli list --format json
Production-ready Kubernetes manifests with Kustomize:
# Preview development deployment
kubectl kustomize deploy/k8s/overlays/development
# Preview production deployment
kubectl kustomize deploy/k8s/overlays/production
# Apply to cluster
kubectl apply -k deploy/k8s/overlays/production
Resource
Description
Deployment
Rolling updates, resource limits, security context (non-root)
Service
ClusterIP for internal communication
HPA
Auto-scaling (3-20 replicas based on CPU/memory)
PDB
Pod disruption budget (minAvailable: 2)
Ingress
With cert-manager TLS annotations
NetworkPolicy
Restrict traffic to namespace
ConfigMap
Environment configuration
Secret
Sensitive data (JWT secret, DB credentials)
📦 Reusable Packages (pkg/)
Error Handling (pkg/apperrors)
import "github.com/hassan123789/go-api-starter/pkg/apperrors"
// Create typed errors
err := apperrors .NewNotFound ("todo" , todoID )
err := apperrors .NewValidation ("email" , "invalid format" )
err := apperrors .NewUnauthorized ("invalid credentials" )
// Check error types (works with errors.Is)
if errors .Is (err , apperrors .ErrNotFound ) {
// Handle not found
}
// Automatic HTTP status mapping
status := apperrors .GetHTTPStatus (err ) // 404, 400, 401, etc.
Generic Utilities (pkg/generic)
import "github.com/hassan123789/go-api-starter/pkg/generic"
// Result type (Rust-like error handling)
result := generic .Ok (fetchData ())
if result .IsOk () {
data := result .Unwrap ()
}
errorResult := generic.Err [int ](errors .New ("failed" ))
// Option type
opt := generic .Some ("value" )
value := opt .UnwrapOr ("default" )
// Functional helpers
numbers := []int {1 , 2 , 3 , 4 , 5 }
evens := generic .Filter (numbers , func (n int ) bool { return n % 2 == 0 })
doubled := generic .MapSlice (numbers , func (n int ) int { return n * 2 })
sum := generic .Reduce (numbers , 0 , func (acc , n int ) int { return acc + n })
Circuit Breaker (pkg/circuitbreaker)
import "github.com/hassan123789/go-api-starter/pkg/circuitbreaker"
cb := circuitbreaker .New (circuitbreaker.Options {
MaxFailures : 5 ,
Timeout : 30 * time .Second ,
HalfOpenLimit : 3 ,
})
err := cb .Execute (ctx , func (ctx context.Context ) error {
return callExternalService (ctx )
})
// With fallback
result , err := cb .ExecuteWithFallback (ctx , primaryFn , fallbackFn )
Worker Pool (pkg/workerpool)
import "github.com/hassan123789/go-api-starter/pkg/workerpool"
// Process items concurrently
results , errors := workerpool .Process (ctx , 10 , items , func (ctx context.Context , item Item ) (Result , error ) {
return processItem (ctx , item )
})
// Pipeline processing
pipeline := workerpool .NewPipeline [Data ]().
AddStage (validate ).
AddStage (transform ).
AddStage (enrich )
result , err := pipeline .Execute (ctx , input )
# Using Taskfile (recommended)
task # Show all available tasks
task build # Build binary
task test # Run tests
task lint # Run golangci-lint (50+ linters)
task check # Run all checks (lint, test, vet)
task docker:up # Start Docker services
task proto # Regenerate gRPC code
# Using Makefile (alternative)
make help # Show all commands
make build # Build binary
make test # Run tests with coverage
make lint # Run linter
# Run all tests
task test
# Run with coverage report
task test:coverage
# Run specific package tests
go test -v ./pkg/circuitbreaker/...
# Run benchmarks
task bench
# Lint with 50+ rules
task lint
# Format code
task fmt
# Security scan
task sec
# Pre-commit hooks (auto-run on commit)
pre-commit install
pre-commit run --all-files
Variable
Description
Default
PORT
HTTP server port
8080
GRPC_PORT
gRPC server port
9090
GRPC_ENABLED
Enable gRPC server
true
DATABASE_URL
PostgreSQL connection string
-
JWT_SECRET
JWT signing key
-
JWT_EXPIRY
Access token expiry
24h
JWT_REFRESH_EXPIRY
Refresh token expiry
168h
LOG_LEVEL
Log level (debug/info/warn/error)
info
OTEL_EXPORTER_JAEGER_ENDPOINT
Jaeger collector URL
-
Architecture Decision Records (ADR)
ADR
Title
001
Adopting Clean Architecture
002
Choosing Echo Framework
003
JWT Authentication Strategy
004
Error Handling Design
005
OpenTelemetry Tracing
006
RBAC Strategy
007
Resilience Patterns
008
Audit Logging
Fork the repository
Create a feature branch (git checkout -b feature/amazing-feature)
Write tests for your changes
Ensure all checks pass (task check)
Commit with conventional commits (git commit -m 'feat: add amazing feature')
Push to your branch (git push origin feature/amazing-feature)
Open a Pull Request
MIT License - see LICENSE for details.
⭐ If this project helps you, please consider giving it a star!