Skip to content
Writing
NewAWSSESMigrationCloudDeliverability

Migrating from AWS SES to SadaSend: Bypassing Sandbox Limits & IAM Complexity

AWS SES is cheap until you spend 3 days navigating AWS IAM policies, submitting support tickets to leave the sandbox, and wrestling with CloudWatch deliverability dashboards.

The hidden engineering tax of AWS Simple Email Service (SES)

Amazon Simple Email Service (AWS SES) is frequently chosen by cloud architects because of its headline pricing: $0.10 per 1,000 sent emails. On paper, it appears to be the most cost-effective transactional email service on the internet.

In practice, however, engineering teams quickly encounter the "hidden AWS tax" — hundreds of engineering hours lost to Byzantine configuration layers, slow operational workflows, and rigid bureaucratic hurdles:

  • The 24-to-72 hour Sandbox Gate: Every new AWS account starts trapped in the SES Sandbox, where you can only send to verified email addresses. Exiting the sandbox requires submitting a manual ticket to AWS Support, detailing your business model, bounce handling architecture, and opt-in mechanics. Startups frequently have their sandbox exit requests denied or delayed for days.
  • The IAM Policy Nightmare: Provisioning sending access requires authorising IAM roles, attaching JSON policy documents, generating SMTP credentials from IAM secret keys, and managing ARN permissions across multiple AWS regions.
  • SNS and SQS Notification Overhead: In AWS SES, basic functionality like receiving bounce or complaint webhooks requires wiring Amazon SNS topics to SQS queues, connecting AWS Lambda dispatchers, and configuring CloudWatch alarms.
  • Heavy SDK Dependencies: Importing @aws-sdk/client-ses adds over 3.4 MB of compiled JavaScript to your serverless functions, increasing AWS Lambda cold starts by 150ms to 300ms.

The 0.05% bounce probation freeze trap

The most hazardous operational danger with AWS SES is its automated reputation enforcement engine. AWS SES enforces a strict account-level probation rule: if your hard bounce rate exceeds 5.0% or your recipient spam complaint rate exceeds 0.1% (1 complaint per 1,000 sends), AWS automatically places your entire AWS account on probation.

If the metrics do not normalize within 14 days, AWS freezes all email sending across all domains and regions in your AWS account. If a rogue signup bot floods your forms with invalid emails, your legitimate customer password resets and invoice dispatches are suspended without appeal.

SadaSend protects your sending domains through an active pre-flight suppression firewall: invalid addresses, previous bounces, and known spam traps are automatically intercepted before reaching recipient mail transfer agents (MTAs), keeping your domain bounce rate below 0.1% under all conditions. Check your DNS records with our free SPF record checker and start sending on our developer pricing plans with 6,000 free monthly emails.

Architecture & Feature Matrix: AWS SES vs SadaSend

The following table compares the operational realities of AWS SES against SadaSend modern edge infrastructure:

Operational VectorAmazon Web Services (SES)SadaSend
Sandbox Exit Time1 to 3 days (Manual AWS review)Instant upon DNS domain verification
SDK Bundle Footprint3.4 MB (@aws-sdk/client-ses)0 KB (Native HTTP Fetch / 12 lines)
Credential ArchitectureIAM Roles, Policies, Secret ARNsSingle scoped Bearer API token
Bounce & Event HandlingRequires SNS + SQS + LambdaBuilt-in real-time webhook endpoints
Autonomous Agent SafetyZero (Unbounded key privileges)Recipient allowlists, approval mode, 10 MCP tools
Edge Dispatch Latency80ms – 180ms (Region-locked)low-latency global Anycast edge
Reputation FreezesAutomatic account-wide suspensionAutomatic pre-flight suppression shield

Step-by-step migration guide: Zero downtime transition

Migrating from AWS SES to SadaSend takes under 15 minutes and requires zero service downtime:

1. Verify Your Domain: Add your sending domain in the SadaSend dashboard. Copy the two CNAME records (2048-bit DKIM) and one TXT record (SPF include:_spf.sadasend.com) to your DNS provider (Route 53, Cloudflare, etc.).

2. Mint Scoped Production API Keys: Create a scoped key in SadaSend with transactional permissions and optional staging allowlists.

3. Update Environment Variables: Replace your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY with SADASEND_API_KEY in your deployment environment.

4. Swap the Dispatch Call: Replace your AWS SDK command with native fetch (or update your SMTP host to smtp.sadasend.com:587).

5. Decommission AWS SNS / SQS Pipelines: Delete legacy SNS bounce topics and CloudWatch alarms once traffic is verified.

Code Migration: Replacing @aws-sdk/client-ses with Native Fetch

Notice how 40 lines of verbose AWS SDK boilerplate and error handling collapse into a clean, readable HTTP request:

TYPESCRIPT
// BEFORE (AWS SES SDK):
// import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';
// const ses = new SESClient({ region: 'us-east-1' });
// await ses.send(new SendEmailCommand({
//   Source: 'billing@yourdomain.com',
//   Destination: { ToAddresses: ['customer@acme.com'] },
//   Message: {
//     Subject: { Data: 'Invoice #1042' },
//     Body: { Html: { Data: '<h1>Your Invoice</h1>' } },
//   },
// }));

// AFTER (SadaSend Native Fetch - Zero Dependencies):
const res = await fetch('https://api.sadasend.com/emails', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.SADASEND_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    from: 'billing@yourdomain.com',
    to: 'customer@acme.com',
    subject: 'Invoice #1042',
    html: '<h1>Your Invoice</h1>',
    text: 'Your invoice is ready.',
  }),
});

if (!res.ok) {
  const error = await res.json();
  throw new Error(`Dispatch failed: ${error.message}`);
}

SMTP Drop-in Migration (Port 587 STARTTLS)

If you use AWS SES via SMTP in Django, Rails, Laravel, or WordPress, you do not need to rewrite any code. Update your environment configuration file:

TEXT
# BEFORE (AWS SES):
SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587
SMTP_USER=AKIAIOSFODNN7EXAMPLE
SMTP_PASS=BPZ9...example

# AFTER (SadaSend):
SMTP_HOST=smtp.sadasend.com
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASS=sada_live_sk_your_key_here
Free plan

Building AI agents that send email?

Scoped API keys, per-key recipient allowlists, approval mode and a hosted MCP server with ten tools — on the free plan, without a card.