Logo

Watermill

Building event-driven applications the easy way in Go.

Get Started See on GitHub

Publish Events

Work with Go structs.
Decouple your services with asynchronous processing.

event := UserRegistered{
    UserID:   id,
    Email:    email,
    JoinedAt: time.Now(),
}

err := eventBus.Publish(ctx, event)

Handle Events

Focus on the business logic.
Watermill handles routing, serialization and low-level details.

eventProcessor.AddHandlers(
    cqrs.NewEventHandler("SendWelcomeEmail", sendWelcomeEmail),
)

func sendWelcomeEmail(ctx context.Context, event *UserRegistered) error {
    return emailService.Send(event.Email, "Welcome!")
}

Simple API you already know

Use the familiar concepts, similar to an HTTP Router with support for middleware.

router.AddMiddleware(
    middleware.Recoverer,
    middleware.CorrelationID,
    middleware.Timeout(30 * time.Second),
)

Use your favorite Pub/Sub

Work with Kafka, RabbitMQ, PostgreSQL, Redis, and more Pub/Subs with the same API. Switch providers without changing your application code.

Library ≠ Framework

Use any architecture you want. No vendor lock-in.

func (h *Handler) RegisterUser(w http.ResponseWriter, r *http.Request) {
    user := createUser(r)

    // Your existing business logic
    err := h.userRepo.Save(user)
    if err != nil {
        // ...
    }

    // Publish an event using Watermill
    err := h.eventBus.Publish(r.Context(), &UserRegistered{...})
    // ...
}
Watermill Logo

Start building