System Architecture
Serverless Inbox is built entirely on AWS serverless services. There are no persistent servers—all compute runs as on-demand Lambda functions, with DynamoDB as the primary data store and S3 for binary storage.
Service Map
Section titled “Service Map”graph LR Clients["Email clients<br/>Webmail UI"] -->|JMAP| JMAP["jmap-api λ"] AdminUI["Admin UI"] -->|REST| Admin["admin-api λ"] SES_IN["AWS SES"] -->|receipt rule| Ingest["email-processor λ"]
JMAP & Admin & Ingest --> DDB[("DynamoDB")] JMAP & Admin & Ingest --> S3[("S3")]Figure 1: The three entry points into the system: email clients via JMAP, admin operations via REST, and inbound email via SES.
Component Overview
Section titled “Component Overview”| Component | Type | Purpose |
|---|---|---|
jmap-api | API Lambda | JMAP protocol handler for email clients |
admin-api | API Lambda | Tenant and user administration |
email-processor | Event Lambda | Processes incoming email from SES |
email-sender | Queue Lambda | Sends outgoing email via SES |
sqs-ses-event-processor | Queue Lambda | Handles SES delivery/bounce/complaint feedback |
websocket-connect/disconnect/message | WebSocket Lambdas | Manage client WebSocket connections |
websocket-broadcast | Internal Lambda | Pushes real-time notifications to connected clients |
audit-writer | Queue Lambda | Persists audit events to DynamoDB |
tantivy-indexer | Scheduled Lambda | Rebuilds full-text search indexes in S3 |
authorizer | Authorizer Lambda | JWT validation for API Gateway |
Data stores
Section titled “Data stores”| Store | Contents | Lifecycle |
|---|---|---|
| MailboxDataStack (Config, Item, Changelog, Audit Log, Mail Feedback tables + S3) | Users, accounts, domains, IDPs, emails, threads, mailboxes, delivery feedback, search indexes | Retained across mailbox stack redeploys |
| DynamoDB JWK cache table | Cached OIDC public keys | Ephemeral—rebuilt on each deploy |
| DynamoDB WebSocket connections table | Active client push connections | Ephemeral—transient session state |
Key Design Choices
Section titled “Key Design Choices”No persistent servers. All compute is Lambda. There are no EC2 instances, containers, or processes to keep alive.
Real-time push via direct Lambda invocation. After writing to DynamoDB, the processing Lambda invokes websocket-broadcast directly. websocket-broadcast looks up active connections and pushes via API Gateway Management API. There is no message bus in this path.
Full-text search is a secondary feature. Simple mailbox queries (the vast majority) read DynamoDB directly. Tantivy is only used for complex text-search queries and runs as an in-process CGO library inside jmap-api, not as a separate service. See Search Architecture for details.
Separate data stack prevents lifecycle conflicts. The five retained DynamoDB tables and S3 bucket live in a separate CloudFormation stack that is never deleted when the mailbox stack is deleted. This enables safe deploy → delete → redeploy cycles without data loss or table recreation.
Go Deeper
Section titled “Go Deeper”- Email Processing Pipeline — Full inbound and outbound email flows
- Search Architecture — How Tantivy integrates with JMAP
- Security Model — Authentication and authorization
- Deployment Models — CDK vs CloudFormation