arm
  • Home
  • Work
  • About
  • Writing
  • Resume
  • Contact
Open to work
❡Case study · Deep dive · 9 min read

EmailOS — an email layer that captures everything and forgets nothing.

Sit in front of Resend or SES, capture every inbound and outbound email, archive it permanently, and give it a searchable inbox.

concepttooltoolinfraconcept
Your email provider's 30-day limit, removed.
Resend, SES, Postmark — every transactional email provider expires your logs. EmailOS is a capture-and-archive layer that sits in front of (or alongside) your existing provider: it intercepts outbound sends, receives inbound via webhook, stores everything permanently in Postgres, and gives you a clean searchable inbox UI. Change providers without losing history. Audit any email ever sent from your app.
∞
Retention
0
Provider lock-in
2
Flows captured
FTS
Search engine
Inbox + email detail view

§01The problem

Every transactional email provider expires logs after 30–90 days. For a small SaaS that means you cannot answer “did this user receive their invite email six months ago?” — the record is gone. For compliance, audits, or debugging a subtle delivery bug, that gap is genuinely dangerous.

The fix sounds simple: just save a copy before you send. The reality is that outbound needs to be proxied or hooked, inbound needs a webhook receiver and an MX setup, and the stored emails need to be queryable, not just archived. EmailOS does all three without replacing your existing provider — it augments it.

§02System architecture

Two capture paths — an outbound proxy SDK and an inbound webhook — feed into a single Postgres store. The UI is a read layer over that store. The provider is swappable at any point; the archive is not touched.

Outbound
Thin SDK wrapperCaptures before sendProvider-agnostic
Inbound
Webhook receiverCloudflare Email RoutingMIME parse
Store
PostgresDrizzle ORMAttachments → R2
Search
Postgres FTSSubject + body indexedRanked results
Inbox UI
Next.js 15Hono APIThread view

§03Three decisions worth defending

Decision 01

Capture at the SDK level, not the provider level

Capturing via provider webhooks means you depend on the provider delivering those webhooks — and you lose the archive if you switch providers. A thin wrapper around the send call captures before the provider is ever involved, so the archive is truly provider-independent.

Decision 02

Attachments to R2, metadata to Postgres

Storing full email blobs in Postgres is an antipattern that makes the database huge and slow. EmailOS stores headers, subject, body text, and thread relationships in Postgres — where they are queryable — and offloads attachment binaries to R2 with a foreign key. Search stays fast; storage stays cheap.

Decision 03

Postgres FTS over a dedicated search service

Email search is overwhelmingly subject-line and sender lookups, not full-document relevance ranking. Postgres tsvector handles that comfortably and keeps the stack to one datastore. Meilisearch or Typesense would be premature for the corpus size EmailOS targets.

§04Hardest problems, plainly

Challenge 01

MIME parsing is a minefield

Real-world emails arrive as multi-part MIME trees — HTML body, plain-text fallback, inline images with Content-ID references, attachments with mismatched charset declarations. Parsing them into a clean stored representation without losing any part required careful handling of every edge case the standard allows and several it does not.

Challenge 02

Threading without a thread ID

Email threading relies on In-Reply-To and References headers — which not every sender sets correctly. Building a thread view that degrades gracefully to subject-line matching when headers are absent, without creating false threads, was more logic than expected.

Challenge 03

Idempotent inbound delivery

Webhook providers retry on timeout. If the receiver is slow, the same email arrives twice. The ingest path deduplicates on Message-ID with an upsert, so replays are safe — but getting that upsert right under concurrent delivery took care with Drizzle's conflict clauses.

“Your email provider owns your logs for 30 days. After that, you never sent those emails. EmailOS fixes that in one SDK line.”— Parm, on EmailOS
Talk about this project →
Open to work

Have something in mind? Let's make it.

iamparmjeetmishra@gmail.com→
GithubMailLinkedInX/Twitter
arm© 2026 — Made with ♡ by Parm
HomeWorkAboutWritingResumeContact