Skip to content

Email delivery

Transactional email (verification, invitations, resets) flows through a provider-neutral adapter with a database outbox + retry worker — an email is recorded before it is sent, and failures retry with backoff instead of silently dropping (ADR-022, ADR-023).

  • Local dev: Mailpit (in the compose stack) catches all mail at http://localhost:8025 — nothing leaves your machine.
  • Staging: Resend, configured purely via environment variables on the deployment host. API keys live only in the staging environment — never in the repo, and never in these docs. Rotate keys via the Resend dashboard and update the host env.
  • Delivery state is inspectable in the email_outbox table; the worker logs retries.

Webhook-driven bounce handling and per-user email preferences are deferred (R-44 in the research backlog).