A practical, opinionated guide to writing idiomatic, scalable Go for backend APIs.
These guidelines are written for teams building backend services in a Go monorepo. They are opinionated by design — the goal is to reduce the number of decisions any developer has to make and create a codebase where every new feature feels natural to add, and every product pivot feels manageable.
These principles run through every guideline. When in doubt, come back to them.
| Principle | What it means |
|---|---|
| Boring is good | Predictable code is maintainable code. A new team member should read any file and understand it without context. Clever code is a liability. |
| Explicit over implicit | Name what you mean. No magic initialization, no hidden dependencies, no surprise side effects. |
| Fail fast, fail loudly | Validate at boundaries. Return errors early. Crash at startup if configuration is invalid. Never silently swallow an error. |
| Composition over hierarchy | Small, focused interfaces compose better than deep type trees. |
| Standard library first | Go's stdlib is excellent. Add a dependency only when the value is clear and the maintenance cost is understood. |
| Don't abstract prematurely | Wait for the third use case before extracting a pattern. The wrong abstraction is worse than duplication. |
| # | Guide | What it covers |
|---|---|---|
| 1 | Project Layout | Monorepo directory structure, where things live and why |
| 2 | Package Design | Naming, cohesion, the internal/ boundary |
| 3 | Architecture | Hexagonal architecture, ports & adapters, dependency direction |
| 4 | Interface Design | Small interfaces, consumer-defined contracts, composition |
| 5 | Error Handling | Wrapping, sentinel errors, error translation boundaries |
| 6 | Dependency Injection | Constructor pattern, explicit wiring, no global state |
| 7 | Concurrency | Goroutines, errgroup, avoiding leaks, channels vs mutexes |
| 8 | Testing | Table-driven tests, mocking strategy, integration tests |
| 9 | Data Access | Repository pattern, sqlc, transactions, migrations |
| 10 | Configuration | Env-based config, fail-fast validation, config structs |
| 11 | Observability | Structured logging, Prometheus metrics, tracing, health checks |
| 12 | HTTP Layer | Chi router, middleware, handler design, request/response DTOs |
| 13 | Tooling | Linting, Taskfile, code generation, developer workflow |
- New to the codebase? Read the guides in order — they build on each other.
- Working on a specific problem? Jump directly to the relevant guide.
- Reviewing a PR? Use the guides as a reference to anchor feedback in shared conventions.
- Disagreeing with a guideline? Open a discussion. Guidelines are living documents — they should evolve as the team learns.