GO-SERVICE-TEMPLATE-SPEC — Go Microservice Starter Repository Specification¶
Status: Draft
Owner: Platform Engineering
Repository: simpaisa/go-service-template
Runtime: Go 1.22+
Last Updated: 2026-04-03
1. Overview¶
Canonical Go microservice starter repository for the Simpaisa platform. Provides a production-ready scaffold for building services that integrate with the Simpaisa infrastructure stack: KrakenD API gateway, SurrealDB, NSQ messaging, gRPC, Caddy sidecar, and OpenTelemetry observability. All Simpaisa Go services SHALL be bootstrapped from this template.
2. Directory Structure¶
go-service-template/
├── cmd/
│ └── {service}/
│ └── main.go # Entry point, wire dependencies, start servers
├── internal/
│ ├── handler/
│ │ ├── http.go # HTTP handlers (REST API)
│ │ └── grpc.go # gRPC service implementations
│ ├── service/
│ │ └── {domain}.go # Business logic layer
│ ├── repository/
│ │ └── {domain}.go # Data access layer (SurrealDB queries)
│ ├── model/
│ │ └── {domain}.go # Domain models and value objects
│ ├── middleware/
│ │ ├── auth.go # RSA signature verification middleware
│ │ ├── logging.go # Request/response structured logging
│ │ ├── tracing.go # OpenTelemetry trace propagation
│ │ └── recovery.go # Panic recovery middleware
│ └── config/
│ └── config.go # Configuration loading (env vars, YAML)
├── pkg/
│ ├── auth/
│ │ ├── rsa.go # RSA key management and verification
│ │ └── merchant.go # Merchant authentication helpers
│ ├── health/
│ │ ├── handler.go # /health and /ready endpoints
│ │ └── checker.go # Dependency health checks (DB, NSQ, etc.)
│ └── telemetry/
│ ├── tracer.go # OpenTelemetry tracer provider setup
│ ├── meter.go # OpenTelemetry meter provider setup
│ └── logger.go # Structured JSON logging (slog)
├── api/
│ └── proto/
│ ├── {service}.proto # gRPC service definition
│ └── buf.yaml # Buf configuration for proto linting
├── deploy/
│ ├── Dockerfile # Multi-stage distroless build
│ ├── Caddyfile # Caddy sidecar configuration
│ └── k8s/
│ ├── deployment.yaml # Kubernetes deployment manifest
│ ├── service.yaml
│ └── configmap.yaml
├── scripts/
│ ├── migrate.sh # Database migration runner
│ └── seed.sh # Development seed data
├── .spectral.yaml # API linting rules (Spectral)
├── .golangci.yaml # golangci-lint configuration
├── Makefile
├── go.mod
├── go.sum
└── README.md
3. Entry Point — cmd/{service}/main.go¶
- Load configuration from environment variables (12-factor)
- Initialise telemetry (tracer, meter, logger)
- Initialise SurrealDB connection pool
- Initialise NSQ consumer/producer
- Wire dependency injection (constructor injection, no frameworks)
- Start gRPC server on configurable port
- Start HTTP server on configurable port
- Graceful shutdown on SIGTERM/SIGINT (drain connections, flush telemetry)
4. KrakenD-Compatible Health Endpoints¶
GET /health — Liveness probe
- Returns 200 OK with {"status": "alive"}
- No dependency checks (fast response for K8s liveness)
GET /ready — Readiness probe
- Checks SurrealDB connectivity
- Checks NSQ producer connectivity
- Returns 200 OK with {"status": "ready", "checks": {...}} or 503 with failed checks
- KrakenD uses this to route traffic only to healthy instances
5. OpenTelemetry (Traces + Metrics + Logs)¶
- Traces: OTLP exporter to collector; W3C TraceContext propagation
- Metrics: OTLP exporter; request duration histogram, error rate counter, active connections gauge
- Logs:
log/slogwith JSON handler; trace ID and span ID injected into every log line - Resource attributes:
service.name,service.version,deployment.environment,service.namespace - Configurable sampling rate (default 10% in production, 100% in sandbox)
- Graceful shutdown flushes all pending telemetry
6. Structured JSON Logging¶
log/slogas the logging abstraction (Go 1.21+ stdlib)- JSON output in production, text output in development
- Standard fields:
timestamp,level,msg,trace_id,span_id,service,request_id - Sensitive fields redacted (PII, keys, tokens)
- Log levels configurable via environment variable:
LOG_LEVEL=debug|info|warn|error
7. SurrealDB Client Wrapper¶
- Connection pool with configurable max connections
- Namespace and database selection from config
- Query helper methods:
Query(),Select(),Create(),Update(),Delete() - Automatic retry on transient connection errors
- Health check method for readiness probe
- Context propagation for tracing
8. NSQ Consumer/Producer¶
Producer:
- Publish to named topics with JSON-serialised messages
- Connection pooling and automatic reconnection
- PublishAsync() for fire-and-forget patterns
- Message envelope: {id, type, timestamp, correlation_id, payload}
Consumer:
- Subscribe to topics with configurable channel names
- Concurrent message handling with configurable MaxInFlight
- Automatic message retry with backoff (NSQ native)
- Dead letter handling after max attempts
- Graceful drain on shutdown
9. gRPC Server¶
- Service definitions in
api/proto/using Protocol Buffers v3 buffor proto linting and breaking change detection- gRPC reflection enabled in non-production environments
- Unary and server-streaming interceptors for auth, logging, tracing
- Health service (
grpc.health.v1) for load balancer integration
10. Caddy Sidecar — Caddyfile¶
:443 {
reverse_proxy localhost:{HTTP_PORT}
tls internal
log {
output stdout
format json
}
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
}
}
- TLS termination at sidecar level
- Security headers injected automatically
- Access logs in JSON format
- Health endpoint passthrough
11. Dockerfile (Multi-Stage Distroless)¶
# Build stage
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /service ./cmd/{service}
# Runtime stage
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /service /service
USER nonroot:nonroot
ENTRYPOINT ["/service"]
- No shell, no package manager in runtime image
- Non-root user by default
- Image size target: < 20MB
12. Makefile¶
.PHONY: build test lint run proto migrate
build: ## Build the service binary
test: ## Run unit tests with race detector
lint: ## Run golangci-lint
run: ## Run locally with hot reload (air)
proto: ## Generate gRPC stubs from proto files
migrate: ## Run database migrations
docker-build: ## Build Docker image
docker-run: ## Run service in Docker
13. CI Pipeline (Bitbucket Pipelines)¶
Stages: lint → test → build → scan → push
- Lint: golangci-lint, buf lint (protos), spectral lint (OpenAPI)
- Test:
go test -race -cover ./...with coverage threshold (>80%) - Build: Multi-arch Docker image (amd64, arm64)
- Scan: Trivy container vulnerability scan; gosec static analysis
- Push: Push image to container registry with semantic version tag
14. API Linting — .spectral.yaml¶
- Enforce Simpaisa API standards on any OpenAPI specs in the repo
- Rules: consistent naming (camelCase), required
operationId, standard error schema, pagination format - Run in CI alongside Go linting
15. Configuration¶
Environment variables (12-factor):
| Variable | Description | Default |
|---|---|---|
SERVICE_NAME |
Service identifier | required |
HTTP_PORT |
HTTP server port | 8080 |
GRPC_PORT |
gRPC server port | 9090 |
SURREALDB_URL |
SurrealDB connection URL | ws://localhost:8000 |
SURREALDB_NS |
SurrealDB namespace | simpaisa |
SURREALDB_DB |
SurrealDB database | required |
NSQ_LOOKUPD_ADDR |
NSQ lookupd address | localhost:4161 |
NSQD_ADDR |
NSQd address for publishing | localhost:4150 |
OTEL_EXPORTER_ENDPOINT |
OTLP collector endpoint | localhost:4317 |
LOG_LEVEL |
Logging level | info |
ENVIRONMENT |
Deployment environment | development |