Technical · 9 min read

AWS SES bounce and complaint handling with SNS — the right way

JR
Jules Rivera
May 4, 2026 · 9 min read
Analytics dashboard showing email bounce data

AWS SES gives you production access and then watches your bounce and complaint rates like a hawk. If either metric crosses the threshold, your sending gets paused. The fix is wiring up Amazon SNS so you process these events in real time.

The two numbers that matter

MetricBest practiceAWS warningAWS pause risk
Bounce rate< 0.5%5%~10%
Complaint rate< 0.05%0.08%~0.1%

Bounce types explained

TypeSubtypeCauseAction
Permanent (hard)GeneralAddress does not existSuppress immediately, never retry
Permanent (hard)NoEmailDomain exists, no mailboxSuppress immediately
Permanent (hard)SuppressedSES account-level suppressionAlready suppressed
Transient (soft)MailboxFullRecipient mailbox is fullRetry after 7 days, suppress after 3 soft bounces
Transient (soft)MessageTooLargeEmail exceeds size limitReduce email size/attachments
Transient (soft)ContentRejectedServer rejected contentCheck for spam trigger words
UndeterminedUndeterminedUnknown reasonRetry once, then suppress

Setting up SNS topic for bounce/complaint notifications

Step 1: Create an SNS topic in the AWS console. Name it ses-notifications. Copy the ARN.

Step 2: In SES Console → Configuration → Configuration Sets → your config set → Event destinations → Add destination. Select SNS. Check Bounces and Complaints.

Step 3: Subscribe an HTTPS endpoint to the SNS topic. SES Mailbox provides this endpoint automatically once you connect your AWS credentials.

# Example SNS bounce notification payload
{
  "notificationType": "Bounce",
  "bounce": {
    "bounceType": "Permanent",
    "bounceSubType": "General",
    "bouncedRecipients": [{
      "emailAddress": "user@nonexistent.com",
      "action": "failed",
      "status": "5.1.1",
      "diagnosticCode": "550 5.1.1 The email account does not exist."
    }],
    "timestamp": "2026-05-04T09:12:33.000Z",
    "feedbackId": "0102abc..."
  },
  "mail": {
    "source": "newsletter@yourdomain.com",
    "destination": ["user@nonexistent.com"],
    "messageId": "0102abc..."
  }
}

Webhook handler example (Node.js)

// Express.js endpoint to process SES SNS notifications
app.post('/webhooks/ses', express.json(), async (req, res) => {
  const message = JSON.parse(req.body.Message);

  if (message.notificationType === 'Bounce') {
    const bounce = message.bounce;
    for (const recipient of bounce.bouncedRecipients) {
      if (bounce.bounceType === 'Permanent') {
        await db.suppressions.upsert({
          email: recipient.emailAddress,
          reason: 'HARD_BOUNCE',
          timestamp: bounce.timestamp,
        });
      }
    }
  }

  if (message.notificationType === 'Complaint') {
    for (const recipient of message.complaint.complainedRecipients) {
      await db.suppressions.upsert({
        email: recipient.emailAddress,
        reason: 'COMPLAINT',
        timestamp: message.complaint.timestamp,
      });
    }
  }

  res.status(200).send('OK');
});

Complaint rate thresholds by ISP

ISPFBL availableComplaint thresholdNotes
GmailAggregate only (Postmaster Tools)< 0.10%Above 0.3% = severe impact on inbox placement
Outlook / HotmailYes (SNDS + JMRP)< 0.08%Also checks Smart Network Data Services reputation
Yahoo / AOLYes (CFL program)< 0.10%Individual complaints forwarded in real time
Apple MailLimited< 0.10%MPP affects open tracking; focus on clicks instead
AWS SES (platform)Via SNS< 0.08% warningPause risk at ~0.1%, AWS enforces independently
Pro tip: Set up a dedicated Configuration Set for marketing and a separate one for transactional email. This isolates complaint rates by email type — so a bad marketing campaign does not damage your transactional email reputation.

What to do if you're already over the threshold

  1. Stop sending immediately
  2. Identify the campaign or segment that caused the spike in SES Mailbox analytics
  3. Run a full suppression of all hard bounces and complaints
  4. Reply to AWS Trust & Safety with your root cause analysis and remediation plan
  5. Restart only with your most-engaged subscribers (opened in last 30 days)
  6. Monitor daily for 2 weeks before returning to full volume

Frequently asked questions

What is the maximum bounce rate allowed by AWS SES? +

AWS warns you at 5% and can pause sending at around 10%, but these are the danger thresholds — not targets. Industry best practice is under 2%. A healthy, well-maintained list should see under 0.5% on any given send. If you are above 2%, pause and clean your list before the next send.

What is the difference between a hard bounce and a soft bounce in SES? +

A hard bounce (bounceType: Permanent) means the address is permanently undeliverable — the mailbox does not exist, or the receiving server explicitly rejected delivery with a 5xx error. Never send to a hard bounce again. A soft bounce (bounceType: Transient) means temporary failure — full mailbox, server down, rate limiting. SES retries soft bounces automatically for up to 72 hours.

Does Gmail send feedback loop (FBL) complaint notifications to SES? +

Gmail does not send individual FBL reports. They only share aggregate domain reputation data through Google Postmaster Tools. Outlook, Yahoo, and most other providers do send FBL reports via SNS. This means your actual complaint rate from Gmail users is invisible at the individual level — only your overall Postmaster Tools domain health score reflects it.

How do I set up SES to automatically suppress bounces and complaints? +

In the SES console, go to Account dashboard → Suppression list settings and enable suppression for both bounces and complaints. This is the account-level suppression list. Additionally, configure SNS notifications on your Configuration Set so that bounce and complaint events fire webhooks to your application or to SES Mailbox for real-time processing.

What should I do if my complaint rate suddenly spikes? +

Stop sending immediately. Identify which campaign or segment caused the spike by looking at per-campaign complaint data in SES Mailbox. Suppress all complainers. Check your recent sends for: missing unsubscribe links, misleading subject lines, sending to cold or inactive segments, or a deliverability partner issue. Only resume sending to your most engaged segment after the spike resolves.

How do I check my current bounce and complaint rates in AWS SES? +

In the SES console: Account dashboard → Sending statistics. You will see your 24-hour sending quota, max send rate, and rolling bounce and complaint rates. SES Mailbox also surfaces per-campaign bounce and complaint rates in the campaign analytics view, and sends alerts when your account-level rates approach the warning thresholds.

Ready to start sending?

Free plan forever. No credit card required.

Start free →