Supermail
Concepts

Data model

Supermail is an event log of change notifications — not a mail store. It never keeps your emails.

The single most important thing to understand about Supermail:

Supermail does not store your emails. It keeps a durable, append-only event log of what changed in each mailbox. The message bodies and attachments themselves are never stored here; they stay at the provider.

An event log, not a mailbox

For every connected account, Supermail maintains an ordered event log: one immutable event per observed change — a message received, a flag flipped, a message deleted, a folder renamed, a sync completing. Message events are thin notifications: they identify the message and its mailbox occurrences, and carry no addresses, flags, attachment descriptors, or body.

This is what Supermail is: a normalization and change-capture layer over messy providers, exposed as one ordered log. It is deliberately not a system of record for mail.

Notifications, not content

Events never carry message content or content handles. Mail metadata and raw bytes reach authorized consumers only through client-owned mail replication and its content lane, which re-fetches the bytes from the provider on demand and streams them as bounded binary frames, never as a JSON-RPC message.

Folding the log into state is your concern

The log tells you what changed. If you want current state — a mailbox mirror, an unread count, a search index — you fold the event log into that state yourself. Supermail intentionally does not maintain it for you.

Folding is straightforward because of two guarantees:

  • Order by (account_id, seq). Each event has a per-account monotonically increasing seq. Apply events in seq order and treat the highest seq you have seen as current.
  • Placements are complete. An email.updated event carries the message's complete current mailbox occurrences, not a diff — so a consumer that missed or reordered an earlier event still converges to the right placement state (the fold is self-healing).

Combined with at-least-once delivery, this means your materializer must be idempotent: deduplicate on event.id and last-writer-by-seq wins.

   provider changes ──▶ Supermail ──▶ append to event log (change notifications)
                                             │
                  list events / webhook push │           your app
                                             ▼
                                   fold into your own state  ◀── you own this

Retention & replay

The log is durable and replayable within a retention window: you can list retained history and receive new events through a webhook consumer. Past the retention window an event is garbage-collected and can only be recovered by re-fetching from the source where the source still has it. This is why consumers that need long-term state keep their own folded copy rather than treating Supermail as permanent storage. The retention window is consumption-derived with a TTL floor and cap — see Events → Retention & recovery for how the buffer drops events, when it redelivers, and how to refetch gaps or the whole window.

On this page