Technical
Email Bounce Handling: The Part Everyone Skips
Every newsletter I have ever shipped had bounces from day one. Hard bounces, soft bounces, complaints. Most projects treat bounces as a nuisance and move on. Skipping the handling is how your sender reputation quietly collapses over six months. Here is the handling pattern I use now and why each piece matters.
The Three Bounce Types
SES classifies delivery problems into three buckets:
- Hard bounce: address is invalid, stop sending to it
- Soft bounce: temporary problem, safe to retry
- Complaint: recipient clicked "spam," stop sending immediately
The fourth thing to care about is deliveries (successful sends). Together they tell you what is happening to your email on the receiving side.
The Event Flow
SES emits events to SNS or EventBridge. I route them to a Lambda that updates subscriber state:
def handle_ses_event(event):
for record in event['Records']:
msg = json.loads(record['Sns']['Message'])
etype = msg['eventType']
email = msg['mail']['destination'][0]
if etype == 'Bounce':
if msg['bounce']['bounceType'] == 'Permanent':
mark_unsubscribed(email, reason='hard_bounce')
elif etype == 'Complaint':
mark_unsubscribed(email, reason='complaint')Hard bounces and complaints immediately mark the subscriber as unsubscribed. No retries, no second chances. Soft bounces are tracked but not acted on unless they repeat.
Why Instant Action Matters
Sending to a known-bad address damages your sender reputation with every provider. Gmail, Outlook, and Yahoo all weigh bounce rate heavily. A 5% bounce rate is the ceiling; above that, your email starts landing in spam folders for everyone, not just the bad addresses.
Complaints are worse. A 0.1% complaint rate is a warning. 0.5% is a suspension risk. Acting on complaints fast is how you stay off AWS's internal blocklists.
The Metric I Watch
Once a day I compute and log:
bounce_rate = hard_bounces / sends
complaint_rate = complaints / sends
deliverability = delivered / sendsI alert if bounce rate goes above 3% or complaint rate goes above 0.2%. Those are both well below the limits but high enough that something is wrong and worth investigating.
The Double-Opt-In Question
The best bounce rate is the one you never generate. Double opt-in (send a confirmation link, require the click) is the single biggest thing you can do to keep bounce rates low. It costs you a few percent of signups in exchange for a list that actually deliverable. Usually worth it.
Read the AWS SES bounce handling guide for the full event schema.
RELATED READING
The Consulting Shift I Am Making In Year Two
After a year of writing and building, my consulting practice is changing shape. Shorter engagements. Sharper outcomes.
ReadThe Frontend Shift: Shipping Less JavaScript In Year Two
A year ago I reached for Next.js for everything. This year I often reach for nothing.
ReadThe Serverless Lesson I Would Write On A Sticky Note
After a year of shipping serverless projects, one rule explains most of the wins and all of the losses.
Read