E-mail layer for Kubernetes

Kourrier

The e-mail layer of a Kubernetes platform: services publish domain events, and declarative routes versioned in Git decide which e-mails go out. Asynchronous, self-hosted and provider-agnostic, written in Go.

Services do not build e-mails: they publish what happened (an account created, an order paid). Kourrier consumes those events and decides, from routes written in a versioned file, which e-mail goes out, to whom and in which language. Sending goes through a queue: it is asynchronous, and retried on failure.

What I built

  • Event-driven input in the CloudEvents format: a NATS JetStream consumer and an HTTP sink. Routes are written in CEL, compiled at startup and testable in CI.
  • Reliable queue on Redis Streams: at-least-once delivery, recovery of jobs from a dead Pod, retries with exponential backoff and a replayable dead-letter queue.
  • Delivery through AWS SES or SMTP behind a single interface; templates stored on S3, MinIO or a local folder; idempotency on both the API and the event side.
  • Hardened Helm chart (non-root, read-only root filesystem, seccomp), shipped with Prometheus metrics, the Grafana dashboard and alerts.

Highlights

  • Safe by default: the default driver sends nothing, and only the SHA-256 hashes of API keys are stored.
  • Distributed rate limiting (GCRA on Redis): the SES quota holds whatever the number of replicas.
  • Sixteen documented architecture decisions (ADRs), from the asynchronous queue to the admin console.