Skip to content

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.

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.


ComponentTypePurpose
jmap-apiAPI LambdaJMAP protocol handler for email clients
admin-apiAPI LambdaTenant and user administration
email-processorEvent LambdaProcesses incoming email from SES
email-senderQueue LambdaSends outgoing email via SES
sqs-ses-event-processorQueue LambdaHandles SES delivery/bounce/complaint feedback
websocket-connect/disconnect/messageWebSocket LambdasManage client WebSocket connections
websocket-broadcastInternal LambdaPushes real-time notifications to connected clients
audit-writerQueue LambdaPersists audit events to DynamoDB
tantivy-indexerScheduled LambdaRebuilds full-text search indexes in S3
authorizerAuthorizer LambdaJWT validation for API Gateway
StoreContents
DynamoDB Items tableEmails, threads, mailboxes, WebSocket connections
DynamoDB Config tableUsers, accounts, domains, IDPs
S3Raw email MIME (inbound/outbound), full-text search indexes

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.