---
name: golang-architecture
description: Use for Go backend directory structure, code placement, dependency layers, module boundaries, infrastructure decoupling, DTO/Domain/PO separation, team conventions, startup/readiness/shutdown lifecycle, and monolith-to-microservice evolution. Go only.
---

# Go Backend Architecture

Choose the smallest architecture that preserves clear dependencies and can evolve with the codebase. Do not start a small service with ceremonial Clean Architecture or let infrastructure details enter business logic.

## Placement card

| Code role | Typical location | Boundary |
| --- | --- | --- |
| HTTP, gRPC, MQ, or cron trigger | `port/`, `handler/`, or `worker/` | Decode, validate, delegate; no business decisions |
| DB, Redis, MQ, framework, or SDK driver | `internal/infra/` | Technical configuration and external dependencies |
| Application workflow | `usecase/` or `service/` | No transport context or raw persistence query |
| Domain entity and consumer-owned ports | `domain/` | No framework, transport, ORM, or infrastructure dependency |
| Reusable utility | `pkg/` only when portable | If it needs project configuration, keep it under `internal/` |

Prefer vertical business modules once layer-wide packages create persistent merge conflicts or cross-domain coupling. Do not use file-count or team-size thresholds as absolute rules; inspect change frequency and domain boundaries.

## Dependency rules

- Dependencies point inward: adapters and infrastructure depend on application or domain abstractions, never the reverse.
- Define interfaces where they are consumed. Infrastructure satisfies them implicitly.
- Keep transport DTOs, domain entities, and persistence objects separate when their contracts evolve independently; conversion code is acceptable at those boundaries.
- Pass `context.Context` as the first parameter for I/O-capable service and repository operations; do not store request contexts on long-lived structs.
- Do not start unowned, unbounded goroutines from request handlers.
- Parse configuration into typed structures at startup instead of scattering string lookups.

## References

- Read [references/architecture-evolution.md](references/architecture-evolution.md) only when choosing a project structure, splitting modules, or planning monolith-to-microservice evolution.
- Read [references/decoupling.md](references/decoupling.md) only when isolating DB, Redis, SDK, transport, DTO, domain, or persistence models.
- Read [references/components.md](references/components.md) only when placing Redis, MQ, consumer, producer, scheduler, or cron code.
- Read [references/production-patterns.md](references/production-patterns.md) only when designing service lifecycle, graceful shutdown, or a shared application error contract.
