Why build it
Most of my work is on the operational side of other people's services. I built this one to keep the other half sharp: a small Go API that does one thing, ships as a tiny image, and behaves predictably when it is killed.
It accepts a JSON payload, writes it to PostgreSQL, and returns a receipt. That is the whole product.
The parts that matter in production
The handlers are the easy part. The interesting decisions are around them:
- Structured logs. Every request logs a request ID, method, path, status, and duration as JSON. No string concatenation, no guessing.
- Graceful shutdown. On
SIGTERM, the server stops accepting connections, waits for in-flight requests, then closes the database pool. - Health checks.
/healthzis liveness./readyzchecks the database connection. They are separate because they answer different questions. - Timeouts everywhere. Server read and write timeouts, a database statement timeout, and a context deadline on every request.
srv := &http.Server{
Addr: cfg.Addr,
Handler: router,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}The image
The build uses a multi-stage Dockerfile: compile with the Go toolchain, then copy the static binary into a distroless base. The result is under 20 MB and has no shell, which makes the attack surface smaller and the pull faster.
FROM golang:1.24 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/api ./cmd/api
FROM gcr.io/distroless/static-debian12
COPY --from=build /out/api /api
ENTRYPOINT ["/api"]What "boring" buys
The service has no framework, no ORM, and no clever abstraction. It starts in milliseconds, exits cleanly, and logs enough to explain itself. When something goes wrong at 2 a.m., boring is a feature.