Go Microservice Scaffold
Generate a production-ready Go HTTP service that follows conventions proven in high-throughput
fintech systems. Prefer the standard library plus a thin router; avoid heavy frameworks.
When to use
- "Create/scaffold a new Go service/microservice/API"
- "Set up a Go backend with health checks and metrics"
- "Add graceful shutdown / Prometheus metrics / Docker to my Go service"
Target layout
<service-name>/
├── cmd/<service-name>/main.go # entrypoint: wire config, server, signals
├── internal/
│ ├── config/config.go # env-based 12-factor config
│ ├── server/server.go # http.Server + routes + middleware
│ ├── handler/ # request handlers
│ └── observability/ # logger + metrics setup
├── Dockerfile # multi-stage, distroless/alpine final
├── Makefile # build, run, test, lint, docker targets
├── go.mod
└── README.md
Conventions (apply these)
- Config — load from environment with sane defaults; fail fast on missing required vars.
Expose
PORT, LOG_LEVEL, and any datastore URLs. Never read config outside internal/config.
- Logging —
zerolog, structured JSON in prod, console writer in dev (driven by LOG_LEVEL/ENV).
Inject a request-scoped logger via middleware; include a request_id.
- Graceful shutdown — listen for
SIGINT/SIGTERM, server.Shutdown(ctx) with a timeout
(default 15s), drain in-flight requests, close datastore pools last.
- Health endpoints —
GET /healthz (liveness, always 200 once up) and GET /readyz
(readiness, checks datastore pings). Keep them unauthenticated and cheap.
- Metrics — expose Prometheus
GET /metrics via promhttp; add a default histogram for
HTTP request duration labelled by route, method, status.
- HTTP server hardening — set
ReadHeaderTimeout, ReadTimeout, WriteTimeout, IdleTimeout.
- Dockerfile — multi-stage: build with
golang:<ver> (CGO_ENABLED=0), final stage on
gcr.io/distroless/static or alpine; run as non-root; copy only the binary.
- Makefile — provide
build, run, test, lint (golangci-lint), docker-build, up.
Steps
- Ask for (or infer) the service name and any datastores (Postgres/Redis/Kafka).
- Create the layout above. Keep
main.go thin — it only wires config → observability → server → signals.
- Generate a minimal but real
/healthz, /readyz, /metrics, and one example domain route.
- Add the Dockerfile, Makefile,
go.mod, and a README with make run / make docker-build.
- Ensure
make build and make test pass before finishing.
Reference snippet — graceful shutdown in main.go
srv := server.New(cfg, logger)
go func() {
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
logger.Fatal().Err(err).Msg("server failed")
}
}()
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
<-ctx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := srv.Shutdown(shutdownCtx); err != nil {
logger.Error().Err(err).Msg("graceful shutdown failed")
}
Keep the generated code small, idiomatic, and immediately runnable with make run.
1---2name: go-microservice-scaffold3description: Use when creating a new Go backend microservice, bootstrapping a Go API, or standardizing an existing Go service to production conventions. Scaffolds an idiomatic layout (cmd/ entrypoint, internal/ packages), 12-factor config loading from env, structured logging with zerolog, context-aware graceful shutdown, liveness/readiness HTTP endpoints, Prometheus /metrics, a multi-stage Dockerfile, and a Makefile. Trigger when the user asks to create, bootstrap, scaffold, or set up a new Go service/API, or to add standard production scaffolding (health checks, metrics, graceful shutdown, Docker) to existing Go code.4license: MIT5---67# Go Microservice Scaffold89Generate a production-ready Go HTTP service that follows conventions proven in high-throughput10fintech systems. Prefer the standard library plus a thin router; avoid heavy frameworks.1112## When to use13- "Create/scaffold a new Go service/microservice/API"14- "Set up a Go backend with health checks and metrics"15- "Add graceful shutdown / Prometheus metrics / Docker to my Go service"1617## Target layout1819```20<service-name>/21├── cmd/<service-name>/main.go # entrypoint: wire config, server, signals22├── internal/23│ ├── config/config.go # env-based 12-factor config24│ ├── server/server.go # http.Server + routes + middleware25│ ├── handler/ # request handlers26│ └── observability/ # logger + metrics setup27├── Dockerfile # multi-stage, distroless/alpine final28├── Makefile # build, run, test, lint, docker targets29├── go.mod30└── README.md31```3233## Conventions (apply these)34351. **Config** — load from environment with sane defaults; fail fast on missing required vars.36 Expose `PORT`, `LOG_LEVEL`, and any datastore URLs. Never read config outside `internal/config`.372. **Logging** — `zerolog`, structured JSON in prod, console writer in dev (driven by `LOG_LEVEL`/`ENV`).38 Inject a request-scoped logger via middleware; include a `request_id`.393. **Graceful shutdown** — listen for `SIGINT`/`SIGTERM`, `server.Shutdown(ctx)` with a timeout40 (default 15s), drain in-flight requests, close datastore pools last.414. **Health endpoints** — `GET /healthz` (liveness, always 200 once up) and `GET /readyz`42 (readiness, checks datastore pings). Keep them unauthenticated and cheap.435. **Metrics** — expose Prometheus `GET /metrics` via `promhttp`; add a default histogram for44 HTTP request duration labelled by route, method, status.456. **HTTP server hardening** — set `ReadHeaderTimeout`, `ReadTimeout`, `WriteTimeout`, `IdleTimeout`.467. **Dockerfile** — multi-stage: build with `golang:<ver>` (`CGO_ENABLED=0`), final stage on47 `gcr.io/distroless/static` or `alpine`; run as non-root; copy only the binary.488. **Makefile** — provide `build`, `run`, `test`, `lint` (golangci-lint), `docker-build`, `up`.4950## Steps51521. Ask for (or infer) the service name and any datastores (Postgres/Redis/Kafka).532. Create the layout above. Keep `main.go` thin — it only wires config → observability → server → signals.543. Generate a minimal but real `/healthz`, `/readyz`, `/metrics`, and one example domain route.554. Add the Dockerfile, Makefile, `go.mod`, and a README with `make run` / `make docker-build`.565. Ensure `make build` and `make test` pass before finishing.5758## Reference snippet — graceful shutdown in main.go5960```go61srv := server.New(cfg, logger)62go func() {63 if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {64 logger.Fatal().Err(err).Msg("server failed")65 }66}()6768ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)69defer stop()70<-ctx.Done()7172shutdownCtx, cancel := context.WithTimeout(context.Background(), 15*time.Second)73defer cancel()74if err := srv.Shutdown(shutdownCtx); err != nil {75 logger.Error().Err(err).Msg("graceful shutdown failed")76}77```7879Keep the generated code small, idiomatic, and immediately runnable with `make run`.