Golang API Server
Priority: P0 (CRITICAL)
Router & GraphQL Selection
- Standard Lib (
net/http): Use for simple services or zero-dependency requirements.http.ServeMux(Go 1.22+) method-based routing. - Echo (
labstack/echo) / Gin: Recommended for production REST APIs with middleware, binding, and error handling. - GraphQL (
99designs/gqlgen): Standard for schema-first GraphQL services. Handlers/resolvers act as thin transport adapters.
Implementation Workflow
- Choose transport layer — REST (Echo/Gin/stdlib) or GraphQL (gqlgen).
- Thin Handlers & Resolvers — Handlers and resolvers parse/validate inputs, invoke use-case services, and map to transport models. Zero direct database queries or business rules.
- Transport-to-Domain Mapping — Domain models remain pure; transport models adapt to domain models via dedicated mappers.
- Response Nullability & Slice Defaulting — Default empty slices to
[](notnull) unless the schema explicitly requires null. Avoid unnecessarynullablefields in GraphQL response schemas when zero-values suffice. - Add middleware — Use middleware for cross-cutting concerns (Logging, Recovery, CORS, Auth, Tracing, RequestID).
- Enforce pagination limits — Support
first/after(GraphQL cursor) orlimit/offset(REST) with strict max caps to prevent memory exhaustion. - Implement graceful shutdown — Handle SIGINT/SIGTERM to drain in-flight requests.
See graceful shutdown example and Echo handler patterns
Anti-Patterns
- No business logic in handlers or resolvers: parse request, call service, and format response only.
- No direct DB calls in resolvers: resolvers must call service interfaces, never execute SQL queries.
- No nil slices in responses: return empty slice
[]rather thannullin API responses unless distinguishing null from empty. - No global router/schema vars: pass router/handler dependencies explicitly via constructor.
- No missing shutdown: handle SIGTERM to drain in-flight requests.
References
- Middleware Patterns
- Graceful Shutdown