AWS SES bounce and complaint handling with SNS — the right way
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
- Bounce rate: AWS warns at 5%, pauses at ~10%. Industry best practice is under 2%.
- Complaint rate: AWS warns at 0.08%, pauses at ~0.1%. Industry best practice is under 0.05%.
These thresholds are rolling, not monthly. A sudden spike — even in a single campaign — can trigger a review.
What are bounces?
A hard bounce means the address is permanently undeliverable — the mailbox doesn't exist, the domain doesn't exist, or the server explicitly rejected delivery. You should never send to a hard-bounced address again.
A soft bounce means temporary failure — the mailbox is full, the server is down. SES retries automatically. You don't need to suppress on a single soft bounce, but chronic soft bouncers (5+ soft bounces) should be suppressed.
What are complaints?
A complaint happens when a recipient clicks the spam button in Gmail, Outlook, or Yahoo. Most ISPs send a Feedback Loop (FBL) notification back to the sender. AWS SES receives these and can forward them to you via SNS.
Gmail does not provide individual FBL reports — they only report aggregate data in Gmail Postmaster Tools. Outlook and Yahoo do provide FBL reports.
Setting up SNS notifications
Step 1: In the AWS SES console, go to Configuration → Configuration Sets → Create a configuration set.
Step 2: Add an SNS event destination to the configuration set. Select the event types: Bounce, Complaint, and optionally Delivery.
Step 3: Create (or use an existing) SNS topic. Subscribe an HTTP/HTTPS endpoint to the topic — this is where SES Mailbox receives the events.
# Example SNS message payload for a hard bounce
{
"notificationType": "Bounce",
"bounce": {
"bounceType": "Permanent",
"bounceSubType": "General",
"bouncedRecipients": [
{ "emailAddress": "user@nonexistent.com", "diagnosticCode": "550 5.1.1 The email account that you tried to reach does not exist." }
],
"timestamp": "2026-05-04T09:12:33.000Z",
"feedbackId": "0102..."
},
"mail": {
"source": "noreply@yourdomain.com",
"destination": ["user@nonexistent.com"]
}
}What SES Mailbox does automatically
SES Mailbox handles all of this for you once you connect your AWS credentials:
- Receives bounce and complaint notifications via SNS in real time
- Automatically suppresses hard-bounced addresses from all future sends
- Automatically suppresses complaint addresses
- Surfaces bounce and complaint rates per campaign in your analytics dashboard
- Alerts you when your account-level rates approach AWS thresholds
Manual suppression — when you need it
If you migrated from another ESP, you should import your historical bounce and complaint list as a suppression list in SES Mailbox before sending your first campaign. This prevents re-contacting known-bad addresses that would immediately spike your rates.
Pro tip: Set up a dedicated Configuration Set for each sending purpose (marketing, transactional). This lets you see bounce and complaint rates broken out by email type — critical for diagnosing which campaigns are damaging your reputation.
What to do if you're already over the threshold
- Stop sending immediately — do not dig the hole deeper
- Identify the campaign or segment that caused the spike
- Suppress the affected addresses (hard bounces + all complainers)
- Reply to AWS Trust & Safety with your root cause analysis and remediation plan
- Restart with a much smaller, highly engaged segment