Email / SMS Delivery (Twilio-like)#
Problem statement (interviewer prompt)
Design a Twilio-style transactional email + SMS delivery service. Accept API calls from customers, route through multiple carriers/providers, manage sender reputation, handle bounces + opt-outs + DLR receipts, and prove deliverability + auditability.
flowchart LR
CUS([Customer])
API[Send API]
Q[[Queue]]
DEL([Channel workers])
SMTP((Email MTAs / SES))
SMS[SMS gateways]
CUS --> API --> Q --> DEL
DEL --> SMTP
DEL --> SMS
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 CUS client;
class API,SMS service;
class Q queue;
class DEL compute;
class SMTP external;
flowchart TB
subgraph Customer
APP([Customer apps])
end
subgraph Edge
GW[API Gateway]
AUTH[API key auth]
IDEM[Idempotency key]
end
subgraph Pipeline
Q[[Kafka per priority]]
TMPL[Template rendering]
LANG[Localization]
SUPP[Suppression list - unsub / bounce]
DEDUP[Dedup window]
end
subgraph Channels
EMAIL([Email workers + MTA])
SMS([SMS workers + carrier APIs])
WHATSAPP[WhatsApp Business API]
VOICE[Voice]
end
subgraph Providers
SES((SES / Sendgrid / Mailgun))
TWILIO((Twilio / MSG91 / carriers))
METAB[Meta Business APIs]
end
subgraph Reliability
RT[Routing per region/carrier]
FALL[Failover provider]
BR[Bounce reasons handler]
REC[Delivery receipts]
DLR([DLR ingest])
end
subgraph Data
CONT[(Contacts)]
HIST[(Send history + events)]
SUPP_DB[(Suppression DB)]
end
Customer --> Edge --> Pipeline
Pipeline --> Channels --> Providers
Providers --> Reliability --> Data
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 APP client;
class GW edge;
class AUTH,IDEM,TMPL,LANG,SUPP,DEDUP,WHATSAPP,VOICE,METAB,RT,FALL,BR,REC service;
class CONT,HIST,SUPP_DB datastore;
class Q queue;
class EMAIL,SMS,DLR compute;
class SES,TWILIO external;
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 |
API gateway / BFF | single ingress, auth, rate limit, routing | api-gateway |
HLD |
Pub/Sub & message brokers | topics, consumer groups, delivery semantics | pub-sub-pattern |
HLD |
Idempotency & retries | safe re-execution, backoff + jitter | idempotency-retries |
LLD |
REST API design | verbs, statuses, pagination, errors | rest-api-design |
LLD |
Async models | futures / async-await / coroutines / actors | async-models |
Quick reference#
Functional#
- Multi-channel send API.
- Templates + localization.
- Suppression / unsubscribe / bounce handling.
- DLR (Delivery Reports) ingest.
- Per-channel routing (region, carrier).
Non-functional#
- p99 send < 2 s for txn.
- 99.9% delivery for valid recipients.
- Bursty (campaign sends).
Trade-offs#
- One provider = simple but risk; multi-provider = failover + costlier ops.
- Throttle per carrier rate cards strictly.
- Reputation: warm IPs, SPF/DKIM/DMARC mandatory.
Refs#
- Twilio architecture talks; SendGrid, Mailgun blogs.
- Postmark on transactional vs marketing.
- AWS SES, GCP Pub/Sub + email integrations.
FAQ#
How does an email and SMS delivery service work?#
Customers call an API. The service routes messages through multiple SMTP or SMS carriers, tracks delivery receipts, retries on transient failures, and exposes events via webhooks.
What is sender reputation and why does it matter?#
Mailbox providers score senders by bounce rate, spam complaints, and engagement. A bad reputation routes messages to spam, so providers warm up IPs and segment traffic carefully.
How does the system handle bounces and complaints?#
Hard bounces are added to a suppression list immediately. Soft bounces are retried with backoff. Spam complaints from feedback loops mark the recipient as opted out.
What is a DLR receipt in SMS?#
A Delivery Receipt is an async ack from the carrier indicating whether the SMS reached the handset. Services correlate DLRs to messages and surface them via webhooks.
How does the service stay compliant with opt-out laws?#
Every send checks a suppression list. Reply keywords like STOP trigger automatic opt-out. The system enforces local rules like CAN-SPAM, GDPR, and TCPA per region.
How are multiple SMTP and SMS providers managed?#
A routing layer chooses providers by cost, deliverability, and destination. On failure it falls over to a backup, ensuring no single carrier outage stops the platform.