Watermill
Go library for building event-driven and messaging systems. Watermill provides a unified pub/sub interface with adapters for Kafka, RabbitMQ, NATS, Redis, SQL, and in-memory transports. Includes router for message processing pipelines, middleware (retry, poison queue, correlation ID), and CQRS/event sourcing helpers. Single API regardless of the underlying message broker.
Score Breakdown
⚙ Agent Friendliness
🔒 Security
TLS and auth delegated to broker adapters. ThreeDotsLabs maintains. No credential storage — broker credentials managed externally.
⚡ Reliability
Best When
You're building a Go event-driven agent system and want broker-agnostic pub/sub with built-in retry, dead letters, and CQRS helpers.
Avoid When
You need maximum Kafka throughput with full control over consumer groups and offsets — use sarama or franz-go directly.
Use Cases
- • Build agent event-driven pipelines where agent events are published to Kafka/NATS and consumed by multiple agent handlers
- • Implement reliable agent message processing with Watermill's built-in retry and dead-letter queue middleware for transient failures
- • Use Watermill's CQRS framework for agent command/event separation — commands trigger domain events, events update read models
- • Build agent pub/sub workflows that run locally with in-memory broker in tests and switch to Kafka in production via config
- • Add correlation IDs and tracing to agent message flows using Watermill's middleware for distributed agent pipeline observability
Not For
- • Simple synchronous agent communication — direct function calls or gRPC are simpler for request-response patterns
- • Very high-throughput streaming — for Kafka-native performance at scale, use sarama or confluent-kafka-go directly
- • Non-Go services — Watermill is Go-only; use Kafka client libraries or cloud pub/sub SDKs for other languages
Interface
Authentication
Auth configured per publisher/subscriber adapter (Kafka SASL, RabbitMQ credentials, NATS JWT). Watermill itself is auth-agnostic — each broker adapter has its own auth configuration.
Pricing
ThreeDotsLabs open source. MIT license.
Agent Metadata
Known Gotchas
- ⚠ Message.Ack() and Message.Nack() must be called for every received message — not calling either blocks the consumer goroutine indefinitely, preventing other messages from being processed
- ⚠ Watermill Router stops all handlers if any handler's publisher returns a permanent error — distinguish transient errors (nack) from permanent errors carefully to avoid stopping the whole router
- ⚠ CQRS framework requires registering all command/event handlers before starting — handlers added after router.Run() are ignored; register all handlers in the bootstrap phase
- ⚠ In-memory publisher/subscriber loses messages on process restart — suitable for testing only; production agents must use durable brokers (Kafka, RabbitMQ) for persistent message delivery
- ⚠ Middleware is applied in reverse registration order for outbound messages — middleware registered last runs first for outbound; same as HTTP middleware but easy to confuse for message ordering
- ⚠ Watermill's GoChannel (in-memory) has a channel buffer of 0 by default — publisher blocks until subscriber reads; configure buffer size for agent pipelines with burst patterns
Alternatives
Full Evaluation Report
Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for Watermill.
Scores are editorial opinions as of 2026-03-06.