Skip to content

Architectures

An architecture defines your project’s structure, dependency rules, and base files.

The hexagonal architecture separates your application into layers with strict dependency direction — inner layers never import from outer layers.

domain/ → Pure business logic, no external dependencies
port/ → Interfaces (inbound use cases, outbound repositories)
service/ → Use case implementations
adapter/ → External integrations (HTTP, DB, messaging)
config/ → Configuration loading (via platform capability)
platform/ → Cross-cutting concerns (via platform capability)
internal/bootstrap/ → Dependency wiring (via bootstrap capability)
cmd/<name>/ → Entry point
ComponentMay Depend On
domainnothing
portsdomain
servicedomain, ports
adaptersports, domain

These rules are enforced by verikt check. If your adapter code imports from another adapter, or your domain imports from service — it’s caught immediately.

Use hexagonal for production APIs and microservices where business logic is complex and you need strict separation of concerns. It’s especially valuable when multiple teams contribute to the same service — the enforced boundaries prevent the accidental coupling that tends to accumulate in flat or layered structures.

A single-package structure with just main.go and go.mod.

main.go
go.mod

Use flat for CLI tools, simple scripts, and quick prototypes where layered structure would add friction without adding value.

The most common architecture pattern — handler, service, and repository layers with a shared model package.

cmd/<name>/ → Entry point
internal/handler/ → HTTP handlers (request/response)
internal/service/ → Business logic
internal/repository/ → Data access
internal/model/ → Shared types and domain models
ComponentMay Depend On
modelnothing
repositorymodel
servicerepository, model
handlerservice, model

Use layered when hexagonal feels like overkill — standard CRUD APIs with straightforward business logic, or teams already fluent in the traditional three-tier pattern who don’t need the port/adapter indirection.

Uncle Bob’s Clean Architecture — entities at the core, use cases orchestrate, interfaces adapt.

cmd/<name>/ → Entry point
internal/entity/ → Core business entities (no dependencies)
internal/usecase/ → Application use cases
internal/interface/handler/ → HTTP handlers, adapters
internal/infrastructure/ → Database, external services, config
ComponentMay Depend On
entitynothing
usecaseentity
interfaceusecase, entity
infrastructureinterface, usecase, entity

Use clean architecture when use cases are the central organizing concept and dependency discipline matters at scale. It’s a good fit for teams already fluent in Uncle Bob’s conventions, or large codebases where strict layering pays for itself.