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

  1. Client calls the Agent service with POST /emails.
  2. Agent writes a PENDING job to DynamoDB and publishes work to SQS.
  3. Email Lambda consumes the SQS message, checks suppression data, and sends through SES.
  4. Lambda updates the job record in DynamoDB to reflect SENT or FAILED.
  5. SES publishes delivery, bounce, and complaint events to SNS.
  6. Event Lambda processes those SNS events, updates DynamoDB, and maintains the suppression list.
  7. Failed deliveries from SQS or SNS end up in their respective DLQs, which can trigger alarms.