A small Go service for creating and retrieving orders, built as a showcase of a hexagonal-architecture HTTP service with an outbox-backed event dispatcher.
- Domain / application / infrastructure split.
internal/domainholds theOrderaggregate and its invariants,internal/applicationholds use cases (commands.CreateOrder,queries.GetOrder) behind port interfaces, andinternal/infrastructureprovides the Postgres and outbox implementations of those ports.internal/transport/httpnever talks to Postgres directly. - Transactional outbox. Writes to the orders table and the outbox table
happen in the same transaction (
internal/infrastructure/store), and a background dispatcher (internal/infrastructure/outbox) polls and publishes outbox rows on an interval, so an order is never persisted without its event eventually being published. - Idempotent writes.
POST /v1/ordersis guarded by an idempotency-key middleware (internal/transport/http/middleware/idempotency.go) backed by a dedicated store, so retried requests are safe. - Observability built in. Structured logging (zap), Prometheus metrics,
and OpenTelemetry tracing are wired through
internal/observabilityand attached as HTTP middleware.
| Method | Path | Description |
|---|---|---|
| POST | /v1/orders |
Create an order (idempotent) |
| GET | /v1/orders/{id} |
Fetch an order by ID |
| GET | /healthz |
Liveness probe |
| GET | /readyz |
Readiness probe |
| GET | /metrics |
Prometheus metrics |
docker compose up --buildThis starts Postgres and the service on :8080 with migrations applied on
boot.
Without Docker:
make migrate # apply migrations against DATABASE_URL
make runAll configuration is via environment variables (see internal/config):
| Variable | Default |
|---|---|
SERVICE_NAME |
orders-service |
APP_ENV |
local |
HTTP_ADDR |
:8080 |
DATABASE_URL |
postgres://orders:orders@localhost:5432/orders?sslmode=disable |
SHUTDOWN_TIMEOUT |
10s |
WORKER_INTERVAL |
2s |
OTEL_EXPORTER_OTLP_ENDPOINT |
(unset — traces log to stdout) |
LOG_LEVEL |
info |
make testRuns go test ./... plus a coverage gate (80%) over the core packages
(excluding cmd/ and the wiring package).