Products / Iris

Iris

Mail that arrives while they're still waiting.

Iris takes the welcome, the password reset and the one-time code from your system, stores each one safely, and delivers it through your own Microsoft 365 or Cloudflare account.

  1. 01

    Nothing lost, nothing sent twice

    A message is stored before Iris answers, retried with back-off, and picked up again after a crash. Repeat a request after a timeout and you get the original message back.

  2. 02

    Your name on every message

    Mail goes out through your own mailbox or domain, under your own SPF and DKIM. Reset links reach people exactly as your system wrote them.

  3. 03

    Nothing left lying around

    Bodies and attachments are dropped as soon as a message is sent. What remains is deleted after 30 days by default.

See it

Send a message:

POST /t/<tenant>/send
→ 202 Accepted, with the message id, once it is safely stored

Pricing

Priced for your deployment

Iris is licensed commercially by Frogfish LLC. Tell us what you want to run, and where, and we'll come back with a price.

Ask for a price

The details

Everything Iris does

Iris is self-hosted transactional mail infrastructure: a single server that takes a message from your system over HTTP, stores it durably, and delivers it through your own Microsoft 365 or Cloudflare account.

It carries the messages a person is waiting for because they just did something: a welcome, a password reset, a one-time code.

What it does

  • Accepts mail over a simple API. POST /t/<tenant>/send with a bearer key answers 202 and a message id once the message is safely stored.
  • Delivers it reliably. Each message has a tracked life: queued, sending, retrying, then sent or failed with the reason. Retries back off from 5 seconds to 5 minutes, honour Retry-After, and run up to 8 attempts.
  • Makes retries safe. With an Idempotency-Key, a caller can repeat a request after a timeout and get the original message back.
  • Survives crashes. An admitted message is sent, or marked failed with the reason. After a kill -9, Iris takes up unfinished work as soon as it restarts. Delivery is at least once.
  • Serves many tenants from one deployment. Each tenant has its own store Heap, keys, senders, provider accounts and delivery loop, so a hung provider stalls only the tenant using it.
  • Sends the exact bytes it was given. Links, bodies and headers reach the provider as the sending system wrote them, and the wording stays with that system, versioned and reviewed with its code.
  • Reports delivery facts. Operators can see each message's state, every attempt, and what the provider said.

Why it matters

  • A reset link is a credential. Because Iris carries links unchanged, that credential stays between the sending system, the provider and the person it was sent to.
  • Sensitive content has a short life. Bodies, attachments and custom headers are dropped as soon as a message is sent or fails. The record that remains is deleted after a retention period, 30 days by default.
  • You keep your sending identity. Mail goes out through your own mailbox or domain, under your own SPF, DKIM and provider relationship.
  • Authentication can depend on it. Senders use keys that Iris issues itself, so Iris and an identity service such as Arbax can each start and work independently, and Arbax can hand Iris its own reset and verification mail.
  • Transactional reputation stays separate. A marketing product sends through Iris as its own tenant, with its own senders and sending domain, away from password resets.

How it is built

  • One Rust binary and one data directory, with the Residiuum database embedded in the process. There is no separate database or queue to run.
  • Two APIs: the runtime API for sending systems, and an operator API for tenants, accounts, senders, keys and messages.
  • Two providers: Microsoft 365 through Graph for mail from a mailbox, and Cloudflare Email Service for mail from a domain. Each account uses the one that fits its address.
  • Any language can call the HTTP API, and Rust callers also have the typed iris-client crate.
  • Settings are IRIS_* environment variables. Iris ships with systemd packaging, /health and /ready endpoints, and structured JSON logs that can be forwarded to Ringtail.
  • Backups dump the store, prove the dump by restoring it, and can go off-site encrypted.

Security

  • API key secrets are 192 random bits, stored as SHA-256 digests. Each key names the senders it may use.
  • The operator API runs on TLS 1.3 with client certificates from a dedicated CA, and every change is logged with the certificate's subject and fingerprint.
  • Provider secrets are stored wrapped, using AES-256-GCM bound to one tenant, account and credential version, or HashiCorp Vault transit. They are unwrapped in memory to send.
  • Logs name messages by id and recipients by domain. Addresses, bodies and secrets stay out of them.
  • Per-tenant send limits, by default 120 a minute and 10,000 a day, answer 429 with Retry-After.

Measured

Iris runs well on a small machine. In its soak test, Iris had a 320 MiB memory budget and one CPU, shared with the test's own load, and sent 50,000 messages across five tenants to a stand-in provider, with 16 concurrent senders:

Admission 499 messages a second
Worst p95 admission latency 103 ms
Delivery of all 50,000 563 seconds, about 89 a second, no duplicates
Peak anonymous memory 290 MiB

A separate full run added a deep queue of 10,000 messages, all delivered, and a kill -9 mid-delivery with nothing lost and a restart in under 4 seconds.

Compared with other options

Iris Hosted email APIs (SendGrid, Postmark, Mailgun, Amazon SES) A mail server (Postfix) Marketing platforms (Mailchimp)
Runs on Your server The vendor's platform Your server The vendor's platform
Sends through Your Microsoft 365 or Cloudflare account The vendor's sending network Your own IPs and reputation The vendor's sending network
Interface HTTP API with idempotent admission HTTP API and SMTP SMTP Web app and API
Where mail content lives In your system; in Iris only until sent Your system, and often vendor templates and logs Your system and the mail queue The platform's templates and campaigns
Built for One-to-one transactional mail Transactional, and often bulk Mail transport of all kinds Campaigns to audiences
Multi-tenancy Built in, with isolated storage and delivery Vendor sub-accounts Configured by hand Vendor accounts
Cost shape Your server, plus your provider's sending Usually per message or plan Your server and deliverability work Usually per contact or plan

Vendor features and pricing change; check them before relying on this table.

Choose Iris when you want a mail API with durable delivery and tenant isolation, running on infrastructure you control and sending under a mail identity you already own.

Where it fits in Frogfish

Iris is the mail layer of the Frogfish ecosystem. Arbax composes its authentication mail and hands it to Iris, and Nurve, a marketing application, sends through it as its own tenant. Iris is live at send.frogfish.io.

More from Frogfish