A demo Go application showcasing the verdastack library for building production-quality web services and CLI tools with OpenTelemetry tracing, Prometheus metrics, and structured logging.
What's inside:
- apigateway -- a reverse proxy that forwards requests to the apiserver with distributed tracing
- apiserver -- a REST API for managing books (CRUD), with an in-memory store
- demo-cli -- a kubectl-style CLI tool that talks to the API and demonstrates Go CLI best practices
The bookstore is intentionally in-memory so the demo can focus on architecture, observability, and command patterns rather than database setup.
See doc/ for focused guides on the patterns demonstrated here:
- Clean Architecture -- folder responsibilities and layering
- Demo Boundaries -- what is real vs simplified
- CLI + Config Pattern -- Cobra, PFlag, Viper wiring
- Web App Observability -- tracing, metrics, and structured logging
- Go 1.22+
- Docker (for the observability stack)
- golangci-lint (optional, for linting)
makeThis compiles all three binaries into bin/.
make infra.upThis runs Grafana Tempo (traces), Prometheus (metrics), and Grafana (dashboards) via Docker Compose.
Open two terminals:
# Terminal 1
make run.apiserver# Terminal 2
make run.apigatewayThe apiserver starts on :8081 and the apigateway on :8080. All client traffic goes through the gateway.
# List all books
$ bin/demo-cli book list
ID TITLE AUTHOR ISBN PRICE
1 The Go Programming Language Alan Donovan & Brian Kernighan 978-0134190440 $39.99
2 Designing Data-Intensive Applications Martin Kleppmann 978-1449373320 $44.99
3 Site Reliability Engineering Betsy Beyer et al. 978-1491929124 $49.99
Showing 3 of 3 book(s).
# Get a single book
$ bin/demo-cli book get 1
ID TITLE AUTHOR ISBN PRICE
1 The Go Programming Language Alan Donovan & Brian Kernighan 978-0134190440 $39.99
# Create a new book
$ bin/demo-cli book create --title "Clean Code" --author "Robert C. Martin" --isbn "978-0132350884" --price 35.99
Book created successfully:
ID TITLE AUTHOR ISBN PRICE
4 Clean Code Robert C. Martin 978-0132350884 $35.99
# Check service health
$ bin/demo-cli status
# Enable debug logging to see HTTP requests/responses
$ bin/demo-cli --log.level=debug book get 1Or use curl directly:
curl http://localhost:8080/api/v1/books
curl http://localhost:8080/api/v1/books/1
curl -X POST http://localhost:8080/api/v1/books \
-H "Content-Type: application/json" \
-d '{"title":"Clean Code","author":"Robert C. Martin","isbn":"978-0132350884","price":35.99}'Open Grafana at http://localhost:3000 (no login required).
- Traces: Explore → Tempo datasource → search by service name (
apigatewayorapiserver) - Metrics: Explore → Prometheus datasource → e.g.
http_server_request_duration_seconds_bucket
| What | URL |
|---|---|
| Gateway metrics | http://localhost:9090/metrics |
| Server metrics | http://localhost:9091/metrics |
| Prometheus UI | http://localhost:9099 |
| Grafana | http://localhost:3000 |
make infra.down # Stop the observability stack
make clean # Remove compiled binaries ┌──────────────┐ HTTP + OTEL ┌──────────────┐
Client ──────► │ apigateway │ ──────────────────► │ apiserver │
│ :8080 │ │ :8081 │
└──────┬───────┘ └──────┬───────┘
│ │
:9090/metrics :9091/metrics
:9090/healthz :9091/healthz
│ │
└──────────┐ ┌────────────────────────┘
▼ ▼
┌──────────────┐
│ Prometheus │◄── scrapes /metrics
│ :9099 │
└──────────────┘
│ │
OTLP gRPC traces OTLP gRPC traces
└──────────┐ ┌────────────────────────┘
▼ ▼
┌──────────────┐
│ Tempo │◄── OTLP :4317
│ :3200 │
└──────┬───────┘
│
┌──────────────┐
│ Grafana │◄── Tempo + Prometheus datasources
│ :3000 │
└──────────────┘
cmd/ Entry points (one per binary)
apigateway/ API gateway
apiserver/ API server
demo-cli/ CLI tool
internal/ Private application code
apigateway/ Gateway server, forwarding handlers
apiserver/ Server, CRUD handlers, store, models
demo-cli/cmd/ CLI commands and utilities
configs/ Service config files (YAML)
build/docker/ Config files for Docker containers
doc/ Design docs and pattern guides
| Target | Description |
|---|---|
make / make build |
Build all binaries into bin/ |
make apiserver |
Build only the apiserver |
make apigateway |
Build only the apigateway |
make demo-cli |
Build only the CLI |
make clean |
Remove bin/ |
make run.apiserver |
Run the apiserver with default config |
make run.apigateway |
Run the apigateway with default config |
make infra.up |
Start Tempo + Prometheus + Grafana |
make infra.down |
Stop the observability stack |
make lint |
Run golangci-lint |
make lint.fix |
Run golangci-lint with auto-fix |
make test |
Run all tests |
make hooks.install |
Set up git pre-commit hooks |
make help |
Show all available targets |
| Package | Purpose |
|---|---|
pkg/app |
CLI framework (Cobra + Viper + flags) |
pkg/server |
Gin HTTP server with graceful shutdown |
pkg/ginx |
Typed request handlers and structured responses |
pkg/otel |
OpenTelemetry provider setup (traces + metrics) |
pkg/middleware/gin |
Trace injection and request logging |
pkg/options |
Server, observability, and TLS config structs |
pkg/errorsx |
Structured error handling |
pkg/metrics |
Prometheus metric registration and helpers |