Lambda Functions
Serverless Inbox runs on a set of purpose-built Lambda functions. They are grouped below by functional area.
All Go lambdas support a shared LOG_LEVEL variable — see Logging configuration at the bottom of this page.
API & Request Handling
Section titled “API & Request Handling”These Lambdas handle synchronous HTTP and authentication requests.
jmap-api
Section titled “jmap-api”The core user-facing API. Implements the JMAP protocol for email read, write, thread, search, and submission. Sits behind API Gateway (HTTP API) and is used by the Webmail UI and any JMAP-capable email client.
Trigger: HTTP API Gateway
Key resources: Config table, Item table, Changelog table, Email bucket, submission queue
Environment variables
| Variable | Description |
|---|---|
CONFIG_TABLE_NAME | DynamoDB config table |
ITEM_TABLE_NAME | DynamoDB item table |
CHANGELOG_TABLE_NAME | DynamoDB changelog table |
EMAIL_BUCKET_NAME | S3 bucket for stored email |
EMAIL_SUBMISSION_QUEUE_URL | SQS queue URL for outbound submission |
AUDIT_EVENTS_QUEUE_URL | SQS queue URL for audit events |
API_BASE_URL | Public base URL of the JMAP HTTP API |
CDN_HOST | CDN host used for attachment URLs |
WEBSOCKET_URL | WebSocket endpoint URL returned in session response |
USER_PROVISIONER_FUNCTION_NAME | Lambda function name for user-provisioner |
OAUTH_HANDLER_CONFIG | JSON config for the OAuth handler |
WEBSOCKET_BROADCAST_FUNCTION_NAME | Lambda function name for websocket-broadcast |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read |
| Item table | read/write |
| Changelog table | read/write |
| Email bucket | read/write |
| Email submission queue | send |
| Audit events queue | send |
user-provisioner Lambda | invoke |
websocket-broadcast Lambda | invoke |
admin-api
Section titled “admin-api”The administrative backend. Handles tenant management, user provisioning, domain and identity configuration, audit log queries, and suppression list management. Used exclusively by the Admin UI and programmatic admin tooling.
Trigger: HTTP API Gateway
Key resources: Config table, Item table, Audit log table, Mail feedback table, Email bucket
Environment variables
| Variable | Description |
|---|---|
CONFIG_TABLE_NAME | DynamoDB config table |
ITEM_TABLE_NAME | DynamoDB item table |
CHANGELOG_TABLE_NAME | DynamoDB changelog table |
AUDIT_LOG_TABLE_NAME | DynamoDB audit log table |
MAIL_FEEDBACK_TABLE_NAME | DynamoDB table for SES bounce/complaint feedback |
EMAIL_BUCKET_NAME | S3 bucket for stored email |
EMAIL_SUBMISSION_QUEUE_URL | SQS queue URL for outbound submission |
AUDIT_EVENTS_QUEUE_URL | SQS queue URL for audit events |
WEBSOCKET_BROADCAST_FUNCTION_NAME | Lambda function name for websocket-broadcast |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read/write |
| Item table | read/write |
| Changelog table | read/write |
| Audit log table | read |
| Mail feedback table | read |
| Email bucket | read/write |
| Email submission queue | send |
| Audit events queue | send |
websocket-broadcast Lambda | invoke |
| SES | GetAccount, CreateEmailIdentity, GetEmailIdentity, GetSendStatistics, ListEmailIdentities, DeleteEmailIdentity, PutEmailIdentityDkimSigningAttributes, SendEmail |
| Route 53 | ChangeResourceRecordSets, ListHostedZonesByName |
| Service Quotas | ListServiceQuotas, RequestServiceQuotaIncrease |
| Lambda | GetAccountSettings |
| STS | GetCallerIdentity |
authorizer
Section titled “authorizer”A shared JWT authorizer invoked by API Gateway before routing requests to jmap-api or
admin-api. Validates the bearer token against the cached public keys, then enforces the
audience, scope, and group requirements configured for each API.
Trigger: API Gateway Lambda Authorizer
Key resources: JWK cache table, Config table
Environment variables
| Variable | Description |
|---|---|
JWK_CACHE_TABLE_NAME | DynamoDB table holding the cached JWKS |
CONFIG_TABLE_NAME | DynamoDB config table |
USER_POOL_ISSUER | OIDC issuer URL |
AUTH_POLICY_NAME | Auth policy record to load from config for scope/group enforcement |
ALLOW_ANONYMOUS | true to allow unauthenticated requests through; defaults to false |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| JWK cache table | read |
| Config table | read |
idp-token-exchange
Section titled “idp-token-exchange”Handles token federation scenarios — for example, exchanging a token issued by an external identity provider for one that satisfies internal audience or scope requirements. Used in advanced auth configurations where the Admin UI or other clients need to present a differently-scoped credential to an internal API.
Trigger: HTTP API Gateway
Key resources: Config table
Environment variables
| Variable | Description |
|---|---|
CONFIG_TABLE_NAME | DynamoDB config table |
AUTH_POLICY_NAME | Auth policy record to enforce on incoming tokens |
OAUTH_CLIENT_NAME | Named OAuth client from config to use for token exchange |
AUDIT_EVENTS_QUEUE_URL | SQS queue URL for audit events; auditing disabled if not set |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read |
| Audit events queue | send (optional) |
Email Processing
Section titled “Email Processing”These Lambdas handle the inbound and outbound email flows. See the Email Processing Pipeline and Email Sending Pipeline for full flow details.
email-processor
Section titled “email-processor”Processes raw incoming emails. Resolves the recipient to a tenant mailbox (handling plus-addressing and alias lookup), stores the message, and triggers real-time push notifications.
Trigger: SQS (fed by SNS from SES inbound receipt)
Key resources: Config table, Item table, Changelog table, Email bucket
Environment variables
| Variable | Description |
|---|---|
CONFIG_TABLE_NAME | DynamoDB config table |
ITEM_TABLE_NAME | DynamoDB item table |
CHANGELOG_TABLE_NAME | DynamoDB changelog table |
EMAIL_BUCKET_NAME | S3 bucket for stored email |
WEBSOCKET_BROADCAST_FUNCTION_NAME | Lambda function name for websocket-broadcast |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read/write |
| Item table | read/write |
| Changelog table | read/write |
| Email bucket | read/write |
websocket-broadcast Lambda | invoke |
email-sender
Section titled “email-sender”Sends queued outbound email submissions. Fetches the stored MIME message, injects server-side signatures, tags the message, and dispatches it via SES.
Trigger: SQS (submission queue)
Key resources: Config table, Item table, Changelog table, Email bucket
Environment variables
| Variable | Description |
|---|---|
CONFIG_TABLE_NAME | DynamoDB config table |
ITEM_TABLE_NAME | DynamoDB item table |
CHANGELOG_TABLE_NAME | DynamoDB changelog table |
EMAIL_BUCKET_NAME | S3 bucket for stored email |
SES_CONFIG_SET_NAME | SES configuration set used for delivery tracking |
WEBSOCKET_BROADCAST_FUNCTION_NAME | Lambda function name for websocket-broadcast |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read |
| Item table | read/write |
| Changelog table | read/write |
| Email bucket | read |
websocket-broadcast Lambda | invoke |
| SES | SendRawEmail |
sqs-ses-event-processor
Section titled “sqs-ses-event-processor”Receives delivery feedback from SES — bounces, complaints, rejections, and delivery confirmations. Updates item state, records feedback, maintains the suppression list, and emits audit events.
Trigger: SQS (fed by SNS from SES event destination)
Key resources: Item table, Mail feedback table, Changelog table, Config table, Audit events queue
Environment variables
| Variable | Description |
|---|---|
CONFIG_TABLE_NAME | DynamoDB config table |
ITEM_TABLE_NAME | DynamoDB item table |
CHANGELOG_TABLE_NAME | DynamoDB changelog table |
MAIL_FEEDBACK_TABLE_NAME | DynamoDB table for SES bounce/complaint feedback |
EMAIL_BUCKET_NAME | S3 bucket for stored email |
AUDIT_EVENTS_QUEUE_URL | SQS queue URL for audit events |
WEBSOCKET_BROADCAST_FUNCTION_NAME | Lambda function name for websocket-broadcast |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read/write |
| Item table | read/write |
| Changelog table | read/write |
| Mail feedback table | read/write |
| Email bucket | read/write |
| Audit events queue | send |
websocket-broadcast Lambda | invoke |
Search
Section titled “Search”tantivy-indexer
Section titled “tantivy-indexer”Maintains per-account full-text search indexes. Reads the changelog to identify changed email items, fetches updated content, and writes updated Tantivy index segments to S3. Runs with elevated memory and a longer timeout to handle batch indexing efficiently.
Trigger: SQS (indexing queue)
Key resources: Email bucket (indexes path), Item table, Config table, Changelog table
Environment variables
| Variable | Description |
|---|---|
ITEM_TABLE_NAME | DynamoDB item table |
CONFIG_TABLE_NAME | DynamoDB config table |
CHANGELOG_TABLE_NAME | DynamoDB changelog table |
INDEX_BUCKET_NAME | S3 bucket where Tantivy index segments are stored |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read |
| Item table | read |
| Changelog table | read |
| Index bucket | read/write |
WebSocket Push
Section titled “WebSocket Push”These four Lambdas together implement the real-time push channel. See the explanation pages for Email Processing and Email Sending for how push notifications are emitted.
websocket-connect
Section titled “websocket-connect”Invoked when a client opens a WebSocket connection. Authenticates the client using the cached JWK keys, then stores the connection registration so the system can push to it.
Trigger: WebSocket API Gateway ($connect route)
Key resources: JWK cache table, Config table
Environment variables
| Variable | Description |
|---|---|
CONNECTIONS_TABLE_NAME | DynamoDB table for active WebSocket connection registrations |
CONFIG_TABLE_NAME | DynamoDB config table |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Connections table | write |
| JWK cache table | read |
| Config table | read |
websocket-disconnect
Section titled “websocket-disconnect”Invoked when a WebSocket connection closes, either by the client or due to timeout. Removes the stored connection registration.
Trigger: WebSocket API Gateway ($disconnect route)
Key resources: Item table
Environment variables
| Variable | Description |
|---|---|
CONNECTIONS_TABLE_NAME | DynamoDB table for active WebSocket connection registrations |
CONFIG_TABLE_NAME | DynamoDB config table |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Connections table | read/write |
| Config table | read |
websocket-message
Section titled “websocket-message”Handles messages sent by connected clients over the WebSocket channel. In the current implementation this is minimal — the push channel is server-initiated.
Trigger: WebSocket API Gateway (default route)
Key resources: Item table
Environment variables
| Variable | Description |
|---|---|
CONNECTIONS_TABLE_NAME | DynamoDB table for active WebSocket connection registrations |
ITEM_TABLE_NAME | DynamoDB item table |
CONFIG_TABLE_NAME | DynamoDB config table |
WEBSOCKET_API_ENDPOINT | WebSocket API endpoint URL for sending messages back to clients |
MAX_SUBSCRIPTIONS | Maximum number of concurrent subscriptions per connection |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Connections table | read/write |
| Config table | read |
| Item table | read |
| API Gateway Management API | execute-api:ManageConnections |
websocket-broadcast
Section titled “websocket-broadcast”Pushes state-change notifications to all registered WebSocket connections for a given account. Invoked directly (not via API Gateway) by other Lambdas that record data changes — for example, after a new email arrives or a message is marked as read.
Trigger: Direct Lambda invocation (from email-processor, email-sender, sqs-ses-event-processor, jmap-api, admin-api)
Key resources: Item table (connection registrations), WebSocket API Gateway Management API
Environment variables
| Variable | Description |
|---|---|
CONNECTIONS_TABLE_NAME | DynamoDB table for active WebSocket connection registrations |
CONFIG_TABLE_NAME | DynamoDB config table |
WEBSOCKET_API_ENDPOINT | WebSocket API endpoint URL for pushing messages to connected clients |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Connections table | read/write |
| Config table | read |
| API Gateway Management API | execute-api:ManageConnections |
System & Lifecycle
Section titled “System & Lifecycle”These Lambdas handle deployment-time setup and background maintenance tasks.
bootstrap
Section titled “bootstrap”A CloudFormation custom resource that runs during CDK deployment. Seeds the Config table with the platform configuration: OIDC provider settings, auth policies, OAuth client definitions, and API endpoint metadata. Runs on every deploy update; designed to be idempotent.
Trigger: CloudFormation custom resource
Key resources: Config table
Environment variables
| Variable | Description |
|---|---|
CONFIG_TABLE_NAME | DynamoDB config table |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read/write |
| IAM | CreateServiceLinkedRole (scoped to servicequotas.amazonaws.com) |
user-provisioner
Section titled “user-provisioner”Creates a user account when invoked by the Admin API or an identity provider webhook. Writes user records, provisions default mailboxes, and records the creation event for auditing.
Trigger: Direct invocation (from admin-api or IdP webhook)
Key resources: Config table, Item table, Changelog table, Audit events queue
Environment variables
| Variable | Description |
|---|---|
CONFIG_TABLE_NAME | DynamoDB config table |
ITEM_TABLE_NAME | DynamoDB item table |
CHANGELOG_TABLE_NAME | DynamoDB changelog table |
AUDIT_EVENTS_QUEUE_URL | SQS queue URL for audit events |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Config table | read/write |
| Item table | read/write |
| Changelog table | read/write |
| Audit events queue | send |
jwk-cache-updater
Section titled “jwk-cache-updater”Periodically fetches the JWKS (JSON Web Key Set) from the configured OIDC issuer and stores the public keys in DynamoDB. This lets the authorizer and websocket-connect Lambda validate JWTs locally without making an outbound call to the IdP on every request.
Trigger: EventBridge scheduled rule
Key resources: JWK cache table
Environment variables
| Variable | Description |
|---|---|
TABLE_NAME | DynamoDB table for storing cached JWK entries |
ISSUERS | Comma-separated list of OIDC issuer URLs to fetch keys from |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| JWK cache table | read/write |
| OIDC provider (internet) | outbound HTTPS — fetches JWKS from each issuer’s discovery endpoint |
audit-writer
Section titled “audit-writer”Consumes audit events from the shared audit SQS queue and writes them to the Audit log table. By routing audit writes through a queue, business-logic Lambdas can emit audit events fire-and-forget without blocking on persistence.
Trigger: SQS (audit events queue)
Key resources: Audit log table
Environment variables
| Variable | Description |
|---|---|
AUDIT_LOG_TABLE_NAME | DynamoDB audit log table |
LOG_LEVEL | See Logging configuration |
AWS resource access
| Resource | Access |
|---|---|
| Audit log table | read/write |
Logging configuration
Section titled “Logging configuration”All Go lambdas use a buffered logging strategy designed to keep CloudWatch Logs quiet during normal operation while retaining full diagnostic context for failures.
Default behaviour (no LOG_LEVEL set): the emit level defaults to error. Debug, info,
and warn messages are written into a 1000-entry in-memory ring buffer instead of CloudWatch.
Only error-level messages are emitted immediately. When an error occurs and the lambda calls
Flush(), the entire ring buffer is dumped retroactively — giving you the debug trail leading
up to the failure without paying the CloudWatch cost on every successful invocation. If the
buffer fills (more than 1000 entries), the oldest entries are silently dropped to make room.
LOG_LEVEL values:
| Value | Behaviour |
|---|---|
| (unset) | Equivalent to error — only errors emitted immediately; everything else buffered |
error | Same as above |
warn | Warn and error emitted immediately; debug and info buffered |
info | Info, warn, and error emitted immediately; debug buffered |
debug | All messages emitted immediately; buffering disabled |
Setting LOG_LEVEL=debug or LOG_LEVEL=info disables buffering for the corresponding levels,
which is useful during development or active incident investigation but increases CloudWatch
volume in production.