Skip to content

Email Service (Gmail)#

Problem statement (interviewer prompt)

Design a Gmail-scale email service: receive via SMTP, store per-user mailboxes durably, deliver outbound via SMTP, support folders/labels, full-text search, threading, attachments, IMAP/POP, and aggressive spam + phishing detection.

flowchart LR
  S([Sender MTA])
  RX[Inbound MTA<br/>SMTP - Postfix]
  AS[Anti-spam / DKIM / SPF / DMARC]
  STORE[(Mailbox Store)]
  IDX[(Search Index)]
  U([User])
  WEB([Web / IMAP / POP])
  S --> RX --> AS --> STORE
  STORE --> IDX
  U --> WEB --> STORE
  U --> WEB --> IDX
  WEB --> SMTPOUT[Outbound MTA] --> Internet

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class S,U,WEB client;
    class RX,AS,SMTPOUT service;
    class STORE,IDX datastore;
flowchart TB
  subgraph Inbound[Inbound path]
    DNS[MX records]
    MTA_IN[Inbound MTA<br/>SMTP 25/465/587]
    TLS[STARTTLS / MTA-STS]
    AUTHV[SPF / DKIM / DMARC / ARC]
    SPAM([Spam classifier<br/>Bayes + ML])
    VIRUS[Malware scan]
    GREY[Greylisting / rate limit]
    ROUTE[Address rewriter / aliases]
  end

  subgraph Storage[Storage Layer]
    BIG[(Bigtable / KV<br/>per-user mailbox)]
    OBJ[(Attachment store)]
    DEDUP[Content dedup<br/>shared blob refs]
    META[(Mailbox metadata)]
    LABEL[Labels / Folders model]
  end

  subgraph Search
    IDX[(Inverted Index<br/>per user)]
    REALTIME[Real-time indexer]
  end

  subgraph User[User access]
    WEB([Web UI])
    IMAP[IMAP / POP / JMAP]
    API[Gmail API]
    PUSH((Push - APNS / FCM))
  end

  subgraph Outbound
    COMPOSE[Compose]
    QUEUE[[Outbound queue]]
    MTA_OUT[Outbound MTA pool]
    DKIM_SIGN[DKIM signing]
    BOUNCE[Bounce / DSN handling]
    REPUTE[IP / domain reputation]
  end

  subgraph Features
    THREAD[Threading - by Subject / Refs]
    PRIO[[Priority Inbox]]
    SMART[Smart Reply / Smart Compose]
    PHISH[Phishing detection]
    LABEL2[Filter / Rule engine]
  end

  subgraph Ops
    QUOTA([Per-user quota])
    RETN[Retention / Deletion]
    AUDIT[Audit log]
  end

  Internet --> DNS --> MTA_IN
  MTA_IN --> TLS --> AUTHV --> GREY --> SPAM --> VIRUS --> ROUTE --> BIG
  BIG --> REALTIME --> IDX
  BIG --> META
  OBJ --- BIG
  DEDUP --- OBJ
  User --> WEB
  WEB --> BIG
  WEB --> IDX
  COMPOSE --> QUEUE --> DKIM_SIGN --> MTA_OUT --> Internet
  MTA_OUT --> BOUNCE
  BOUNCE --> COMPOSE
  REPUTE --- MTA_OUT
  Features --- BIG
  Ops --- BIG

    classDef client fill:#dbeafe,stroke:#1e40af,stroke-width:1px,color:#0f172a;
    classDef edge fill:#cffafe,stroke:#0e7490,stroke-width:1px,color:#0f172a;
    classDef service fill:#fef3c7,stroke:#92400e,stroke-width:1px,color:#0f172a;
    classDef datastore fill:#fee2e2,stroke:#991b1b,stroke-width:1px,color:#0f172a;
    classDef cache fill:#fed7aa,stroke:#9a3412,stroke-width:1px,color:#0f172a;
    classDef queue fill:#ede9fe,stroke:#5b21b6,stroke-width:1px,color:#0f172a;
    classDef compute fill:#d1fae5,stroke:#065f46,stroke-width:1px,color:#0f172a;
    classDef storage fill:#e5e7eb,stroke:#374151,stroke-width:1px,color:#0f172a;
    classDef external fill:#fce7f3,stroke:#9d174d,stroke-width:1px,color:#0f172a;
    classDef obs fill:#f3e8ff,stroke:#6b21a8,stroke-width:1px,color:#0f172a;
    class WEB,QUOTA client;
    class DNS,MTA_IN,TLS,AUTHV,VIRUS,GREY,ROUTE,DEDUP,LABEL,REALTIME,IMAP,API,COMPOSE,MTA_OUT,DKIM_SIGN,BOUNCE,REPUTE,THREAD,SMART,PHISH,LABEL2,RETN service;
    class BIG,OBJ,META,IDX datastore;
    class QUEUE,PRIO queue;
    class SPAM compute;
    class PUSH external;
    class AUDIT obs;

Mailbox storage#

  • Per-user mailbox in a sharded KV (Gmail historically on Bigtable; Yahoo on Cassandra-ish).
  • Message keyed by (user_id, msg_id); immutable body + mutable flags & labels.
  • Attachments stored once in object store, referenced by content hash (dedup).
  • Search index is per-user inverted index.

Threading#

  • RFC 2822 In-Reply-To / References headers form thread graph; fall back to normalized Subject.
  • Gmail-style label-based threading vs Outlook-style folder model.

Anti-spam stack#

  1. Connection-time checks (RBL, rate, greylisting).
  2. Auth: SPF (sender IP allowed), DKIM (signature match), DMARC (policy alignment), ARC (forwarded chain).
  3. Content classifier (Bayes + ML + reputation).
  4. User feedback ("Report spam") fed back into models.

Outbound reputation#

  • Warm IPs gradually; SPF + DKIM on every send.
  • Bounce processing → list hygiene.
  • Real-time indexing on receive (within seconds).
  • Per-user inverted index avoids cross-tenant leaks.

Scale notes#

  • Billions of mailboxes; some > 10 GB.
  • Attachment dedup saves significant storage (same forwarded chain).
  • IMAP idle keeps connections persistent → many open sockets.

Glossary & fundamentals#

Concepts referenced in this design. Each row links to its canonical page; the tag column shows whether it is a high-level (HLD) or low-level (LLD) concept.

Tag Concept What it is Page
HLD Search internals inverted index, BM25, embeddings, ANN search-internals
LLD Immutability immutable types, persistent collections immutability

Quick reference#

Functional#

  • Receive (SMTP), store, deliver.
  • Send via SMTP outbound.
  • Per-user folders/labels; threads.
  • Full-text search.
  • Spam, malware, phishing detection.
  • IMAP/POP for clients; web UI.
  • Attachments, signatures (S/MIME, PGP optional).

Non-functional#

  • 99.99% availability for inbound (loss = lost mail).
  • Deliver within seconds normally; minutes during incidents.
  • 1B+ mailboxes, 10s of B msgs/day.

Capacity#

  • 50B msgs/day × 50 KB avg = 2.5 PB/day raw.
  • Per user: avg 5-10 GB mailbox.
  • Attachment dedup saves 30-50%.

Schema (per-user mailbox)#

  • messages(user_id, msg_id, thread_id, headers, body_ref, labels[], read)
  • threads(user_id, thread_id, subject, last_msg_ts)
  • index_terms(user_id, term, msg_ids[]) posting list

Trade-offs#

  • Per-user partitioning simplifies isolation and search but breaks aggregate analytics.
  • Bigtable / Cassandra preferred over RDB at scale; transactions are per-user.
  • Threading by Subject can over-merge unrelated mails; modern Gmail uses Refs.
  • Server-side rules vs client filters: server-side scales but harder UX.
  • End-to-end encryption (S/MIME, PGP) cripples search and spam - niche.

Refs#

  • Gmail architecture talks (Bigtable + search), RFC 5321 (SMTP), RFC 5322 (Mail format), DMARC.org docs, "Gmail outage post-mortems."

FAQ#

How does an email service handle inbound SMTP?#

MX records point to an inbound MTA cluster. Postfix or a custom MTA accepts the message, runs spam and DKIM/SPF/DMARC checks, and writes the body to durable mailbox storage.

How does Gmail-scale spam filtering work?#

Layered filters combine sender reputation, DKIM/SPF/DMARC verdicts, content classifiers, URL reputation, and user-feedback signals. Borderline messages route to Spam folder.

Where are mailboxes stored at scale?#

Append-only blob storage holds message bodies. A per-user metadata DB stores labels, threading, flags, and message IDs, sharded by user with replicas for HA.

Index each message into per-user inverted indexes with terms, attachments, and labels. Sharded Elasticsearch or a custom Lucene fleet serves user-scoped queries fast.

What are DKIM, SPF, and DMARC?#

SPF authorizes sending IPs by DNS, DKIM signs message headers with a key in DNS, and DMARC tells receivers what to do when SPF or DKIM fails. Together they curb spoofing.