Production-ready template for building asynchronous RabbitMQ workers in Go.
- Message routing via ThreeDotsLabs/watermill + watermill-amqp
- Middleware pipeline: structured logging, configurable retry with backoff, panic recovery, Prometheus metrics
- Diagnostic HTTP server:
/pinghealthcheck,/metrics(Prometheus),/debug/pprof/*profiling endpoints - Structured logging via uber-go/zap with optional Sentry integration
- Graceful shutdown on OS signal
- Environment-based configuration via kelseyhightower/envconfig
.
├── cmd/ # Entrypoint
├── internal/
│ ├── app/
│ │ ├── config/ # Configuration (envconfig)
│ │ ├── logger/ # Zap logger setup
│ │ └── server/ # Diagnostic HTTP server
│ ├── middleware/ # Logging, retry, recoverer, metrics
│ ├── publishers/pub/ # AMQP publisher
│ ├── subscribers/sub/ # AMQP subscriber + message handler
│ ├── marshalers/ # Message marshaling
│ ├── metrics/ # Prometheus metrics
│ ├── httpclients/ # HTTP client wrapper
│ └── retryable/ # Retryable error types
├── scripts/
└── docker-compose.dev.yml
All configuration is done via environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
RMQ_USER |
yes | — | RabbitMQ username |
RMQ_PASSWORD |
yes | — | RabbitMQ password |
RMQ_HOST |
yes | — | RabbitMQ host |
RMQ_PORT |
yes | — | RabbitMQ port |
RMQ_VHOST |
yes | — | RabbitMQ virtual host |
RMQ_EXCHANGE |
yes | — | Exchange name |
RMQ_QUEUE |
yes | — | Queue name |
RMQ_ROUTING_KEY |
yes | — | Routing key |
RMQ_QOS_PREFETCH_COUNT |
no | 1 |
QoS prefetch count |
MAX_RETRIES |
no | 5 |
Max message processing retries |
RETRIES_INTERVAL |
no | 3s |
Initial retry backoff interval |
SERVER_LISTEN_ADDR |
no | 0.0.0.0:8080 |
Diagnostic HTTP server address |
SERVER_READ_TIMEOUT |
no | 3s |
HTTP server read timeout |
SERVER_WRITE_TIMEOUT |
no | 3s |
HTTP server write timeout |
LOG_LEVEL |
no | debug |
Log level |
SENTRY_DSN |
no | — | Sentry DSN for error reporting |
docker-compose -f docker-compose.dev.yml up -dmake build
make run-servermake run-devmake testOr just tests (without lint):
./scripts/test.shmake golangci| Endpoint | Description |
|---|---|
GET /ping |
Health check |
GET /metrics |
Prometheus metrics |
GET /debug/pprof/* |
pprof profiling endpoints |
The message handler is located in internal/subscribers/sub/subscriber.go. Implement your business logic inside the Handler method:
func (s *Subscriber) Handler(msg *message.Message) error {
// your logic here
return nil
}To make an error retryable (triggers the retry middleware), wrap it with the retryable error type from internal/retryable/errors.go.
- Branch with cobra + viper CLI — variant using spf13/cobra + spf13/viper