Agent → Email Service Architecture
High-throughput, async, durable email pipeline. Agent (ECS) enqueues; Email (Lambda) sends via SES; DynamoDB is source of truth; SQS/SNS decouple producers from consumers.
Components
| Component | Role |
|---|---|
| Agent (ECS Fargate, NestJS) | API surface. Accepts single/batch send requests, writes job rows to DynamoDB, publishes to SQS. |
| Email Lambda (plain Node/TS) | SQS-triggered worker. Renders + sends via SES, updates DynamoDB. No DI framework — handler is a plain function for fast cold starts. |
| Event Lambda (plain Node/TS) | SNS-triggered. Updates job status, maintains suppression. |
SQS Standard (email-jobs) |
Main work queue. High throughput, at-least-once. |
SQS DLQ (email-jobs-dlq) |
Catches messages exceeding maxReceiveCount. |
SQS DLQ (event-lambda-dlq) |
Catches SNS deliveries Event Lambda failed to process after retries. |
SNS (ses-events) |
Fan-out for SES bounce/complaint/delivery notifications. |
DynamoDB EmailJobs |
Job state, idempotency, audit trail. |
DynamoDB Suppression |
Bounce/complaint suppression list (checked before send). |
| SES | Actual mail transport. |
High-Level Flow
- Client calls the Agent service with
POST /emails. - Agent writes a
PENDINGjob to DynamoDB and publishes work to SQS. - Email Lambda consumes the SQS message, checks suppression data, and sends through SES.
- Lambda updates the job record in DynamoDB to reflect
SENTorFAILED. - SES publishes delivery, bounce, and complaint events to SNS.
- Event Lambda processes those SNS events, updates DynamoDB, and maintains the suppression list.
- Failed deliveries from SQS or SNS end up in their respective DLQs, which can trigger alarms.