Amazon SES Hard Bounce Forensics: A Diagnostic Playbook

Amazon SES Hard Bounce Forensics: A Diagnostic Playbook

Why a Hard Bounce Spike Demands Immediate Action

A hard bounce spike in Amazon SES is not a metric to review at your next sprint retrospective. It is a live incident with a tight clock. AWS operates a two-tier enforcement model: a bounce rate of 5% or above places your account under review, and a rate of 10% or above can result in sending being paused entirely. Either outcome is damaging. Under review, you must submit a remediation plan before normal service resumes. A full pause stops everything at once: password resets, order receipts, invoices, onboarding sequences, and every other email your product depends on.

The account-level nature of SES reputation makes the problem worse. A single bad batch sent to an unverified segment can push the rolling average over the 5% review threshold before anyone on the team has noticed a problem. AWS will open a support case and send a notification, but by then the damage to your sending infrastructure and your domain reputation with major mailbox providers is already accumulating. The goal of this playbook is to give you a disciplined diagnostic workflow you can execute the moment a spike appears, not after AWS has already acted.

How SES Reports Hard Bounces: The SNS Notification JSON

Before you can diagnose anything, you need to be reading the right data. SES publishes bounce, complaint, and delivery notifications to Amazon SNS topics in JSON format. Understanding the structure of a bounce notification is the foundation of every diagnostic step that follows.

The top-level object contains a notificationType field set to "Bounce", a mail object describing the original message, and a bounce object containing the diagnostic detail. One important note: when you use configuration sets with event publishing rather than the older feedback-forwarding path, this top-level field is named eventType instead of notificationType. Your parser must handle both. Within the bounce object, the fields you care most about are bounceType, bounceSubType, bouncedRecipients, reportingMTA, and timestamp. Inside bouncedRecipients, each entry carries an emailAddress, an action (typically "failed" for hard bounces), a status field containing the enhanced SMTP status code such as 5.1.1, and a diagnosticCode containing the raw SMTP response string from the receiving server.

The bounceType field will be one of three values: Permanent, Transient, or Undetermined. Hard bounces always carry bounceType: "Permanent". The bounceSubType narrows the cause further. A value of General is the most common and indicates a standard permanent rejection. A value of NoEmail means the address does not exist at the recipient domain. A value of Suppressed means SES has suppressed the send because the address appears on the global SES suppression list, which is managed by AWS across all customers to protect shared IP reputation. A value of OnAccountSuppressionList means the address was on your own account-level suppression list before you attempted delivery.

The diagnosticCode field contains the receiving server's full SMTP rejection string. An example looks like this: smtp; 550 5.1.1 user unknown. This raw string is your single most valuable diagnostic signal and the first thing you should pull from every bounce record during an incident.

The Three Root Causes of a Hard Bounce Spike

Almost every hard bounce spike traces back to one of three root causes, or a combination of them: list quality decay, authentication misconfiguration, and IP or domain reputation rejection. Identifying which one is driving your spike determines every action you take next. Conflating them leads to wasted effort and continued sending damage.

List quality decay means you are attempting to deliver to addresses that no longer exist or never did. Authentication misconfiguration means a change to your DNS records, DKIM selectors, or sending infrastructure has broken the signals receivers use to verify you are who you claim to be. IP or domain reputation rejection means a mailbox provider or blocklist operator has decided your sending source is untrustworthy and is returning hard rejections as a result. The diagnostic data in your bounce notifications will distinguish between them; the SMTP status codes and the raw diagnosticCode strings are your compass.

Decoding SMTP 5xx Status Codes

Every hard bounce carries a 5xx SMTP code. The three-digit code identifies the failure class, and the enhanced status code of the form X.Y.Z narrows the cause to a specific category. The first digit confirms a permanent failure. The second digit identifies the subject area: 1 for addressing, 2 for mailbox status, 4 for network or routing, 7 for security and policy. The third digit provides the specific detail within that subject. Reading the enhanced code rather than just the human-readable sentence is essential because receiving servers write those sentences however they choose; the codes are standardised.

The following codes appear most frequently in SES bounce notifications and each points to a distinct diagnostic conclusion.

5.1.1 The recipient address does not exist at the destination domain. This is the most frequently seen hard bounce code and points directly to list quality: addresses that were mistyped at signup, that have been deleted, or that belong to domains that no longer accept mail.

5.1.2 The recipient domain does not exist or cannot be resolved in DNS. This indicates a domain-level addressing problem rather than a mailbox-level one. Common causes include typos in the domain portion of the address, expired domains, or domains that have been decommissioned.

5.4.1 No answer from the recipient host. The DNS lookup for the domain succeeded but the mail server is unreachable. This can reflect a temporary outage that the receiving server has resolved as a permanent failure, but it also appears when a domain has removed its MX records entirely.

5.7.1 Delivery not authorised. This code covers the widest range of causes and requires careful reading of the accompanying diagnosticCode string. It can indicate a content or policy rejection by the receiving server, an IP-level blocklist rejection, or a DMARC policy enforcement rejection. The free-text portion of the diagnostic string will usually distinguish between them.

5.7.23 SPF validation failed. The receiving server checked your SPF record and the sending IP was not authorised. This points unambiguously to an authentication problem.

5.7.26 DMARC validation failed. Gmail in particular returns this code when a message fails DMARC alignment. If you see this code spreading across multiple recipients at a major mailbox provider, authentication is your root cause.

5.0.0 A generic permanent failure with no further classification. Inspect the raw diagnosticCode string for the receiving server's explanation, which may reference a blocklist, a content filter, or a specific policy rule.

Step 1: Isolate the Spike to a Configuration Set, Domain, or Campaign Segment

The first action in any bounce incident is to establish the blast radius. A spike that affects your entire account points to something systemic: an authentication break or an IP blocklist hit. A spike confined to a single configuration set or sending domain points to a campaign or segment-level problem. A spike that appeared immediately after a new batch was sent to a recently imported list points strongly to list quality.

Pull your bounce events from your SNS topic or event destination and group them by the mail.sourceArn field, which identifies the sending identity, and by the configuration set name embedded in the message tags. Cross-reference the timestamps: do the bounces cluster around a specific send, or are they spread evenly across your normal sending pattern? A sudden vertical spike on a time-series chart of bounce volume almost always means a discrete batch was the cause rather than a gradual degradation.

Also check the reportingMTA field across your bounce records. If you are on dedicated IPs and the bounces all reference the same sending IP, the problem may be concentrated on that IP's reputation. If the reportingMTA values are mixed across different IPs, the problem is more likely in the content or the recipient list than in any single IP.

Step 2: Rule Out Authentication as the Cause

Authentication failures are particularly dangerous because they can generate hard bounces at scale across otherwise valid addresses. If your DKIM selector has drifted because a DNS change was made without updating the CNAME records SES requires, every message you send will fail DKIM verification. If your domain has a DMARC policy set to p=reject and neither SPF nor DKIM is achieving alignment, receivers enforcing that policy will reject your mail permanently.

For DMARC alignment to pass, either SPF or DKIM must align with the From domain. For SPF alignment, the Mail From domain must match or be a subdomain of the From domain. For DKIM alignment, the d= value in the DKIM signature must match or be a subdomain of the From domain. If you are using a custom MAIL FROM domain in SES, verify that the subdomain's MX and SPF records are correctly published. If you are relying on DKIM for alignment, confirm that the three CNAME records SES requires for Easy DKIM are still present in your DNS provider and are resolving correctly.

The diagnostic signal for an authentication root cause is a concentration of 5.7.23, 5.7.26, or 5.7.1 codes in your bounce records, with the diagnosticCode strings referencing SPF or DMARC. If you see these codes spreading across multiple recipient domains including Gmail and Yahoo, authentication is almost certainly the cause. Also audit your SPF lookup chain: the SPF specification limits evaluation to ten DNS lookups, and including multiple include: mechanisms can silently exceed that limit, causing SPF to fail with a permerror result that strict receivers treat as a permanent failure.

Step 3: Assess List Quality

If authentication checks out cleanly and your bounce codes are dominated by 5.1.1 and 5.1.2, the problem is in your list. Address-level rejections mean you are attempting to deliver to mailboxes that do not exist. The diagnostic questions to ask are: how old is the segment you just sent to, where did these addresses come from, and have you sent to this segment recently?

Email lists decay at a meaningful rate over time as people change jobs, abandon accounts, and let domains lapse. A segment that was last mailed twelve months ago will have a materially higher proportion of invalid addresses than one mailed last week. Purchased or scraped lists are an obvious red flag, but decay also affects organically acquired lists if re-engagement practices are not in place.

Examine the recipient domains in your bounce records. A high proportion of bounces from a small number of domains can indicate that those domains had catch-all configurations that accepted every address at signup but are now returning permanent failures at delivery time. Role-based addresses such as info@, admin@, and noreply@ are disproportionately likely to hard bounce or generate complaints and should be screened out of marketing sends. Finally, check whether the affected addresses were already on your SES account suppression list. If you are seeing bounceSubType: "OnAccountSuppressionList" in your notifications, those addresses were known bad before the send, which indicates a gap in your pre-send suppression check.

Step 4: Check IP and Domain Blocklist Status

If your bounce codes are dominated by 5.7.1 with diagnostic strings referencing terms such as "blocked", "listed", or naming a specific blocklist operator, your sending IP or domain has been listed. This is a distinct cause from authentication failure and requires a different remediation path.

On SES shared IP pools, a listing of a specific IP may affect your sending without any fault in your own practices. On dedicated IPs, a listing almost always traces back to a spike in complaints or bounces from your own sending. Check the remoteMtaIp field in your bounce notifications to identify which IP is generating the rejections, then query the major public blocklist databases for that IP. The blocklists that most commonly affect SES delivery include Spamhaus ZEN and Barracuda.

For domain-level reputation problems, the diagnostic strings will often name your sending domain explicitly. Google, Microsoft, and Yahoo all return human-readable messages in the diagnosticCode field that describe their reason for rejection. A message referencing your sending volume, content patterns, or complaint history indicates that the receiving provider's own reputation system has flagged your domain rather than a third-party blocklist, and the remediation path is different in each case.

Step 5: Implement an Emergency Suppression Loop and Stop the Bleeding

While you are diagnosing the root cause, you must simultaneously stop adding to the bounce count. Every additional hard bounce sent to an already-bounced address compounds your rate without any prospect of delivery. SES automatically adds hard-bounced addresses to your account-level suppression list, but this only prevents future SES sends to those addresses. It does not prevent your application from attempting to send if your own database still contains those addresses without the suppressed flag.

Set up a consumer on your bounce SNS topic that writes every Permanent bounce to a suppression store in your own system and cross-references it before any send is attempted. For the immediate incident, pause any scheduled campaigns or automated sequences that target the affected segment. If the spike was triggered by a specific batch job, disable that job until the root cause is confirmed and resolved.

If you need to halt sending programmatically, the SES API provides account-level and configuration-set-level controls for pausing sending. In the SES v2 API, use PutAccountSendingAttributes to pause at the account level; in the older v1 API, the equivalent operation is UpdateAccountSendingEnabled. A controlled pause you initiate is far less damaging than an enforced pause imposed by AWS after the 10% threshold is breached.

Building a Permanent Early-Warning System

The goal after resolving an incident is to ensure the next spike is caught within minutes rather than discovered via an AWS enforcement notification. The SES reputation dashboard shows your current metrics, but it does not push alerts; it requires you to check it actively. AWS best practice is to configure CloudWatch alarms on the Reputation.BounceRate metric in the AWS/SES namespace, with warning thresholds set well below the enforcement levels. A common approach is a warning alarm at 2% and a critical alarm at 4%, giving you room to act before the 5% review threshold is reached.

Per-domain and per-configuration-set visibility matters just as much as account-level metrics. Account-level figures mask problems that are localised to a single sending domain or campaign. If you send from multiple domains, you need to know when one domain's bounce rate is rising even while the overall account rate remains within bounds.

SES Monitor provides real-time bounce and complaint alerting built directly on the SNS event pipeline, so spikes are surfaced as they happen rather than on the next dashboard refresh. Per-domain rate tracking shows exactly which sending identity is driving a change, and automated suppression webhooks feed bounce data directly into your CRM or list management system the moment an event arrives. The difference between catching a spike at five minutes and catching it at five hours is often the difference between a contained incident and an account enforcement action.

Conclusion

A hard bounce spike in Amazon SES is a sequenced diagnostic problem, not a single mystery to solve. Start by reading the raw JSON from your SNS bounce topic. Use the bounceType, bounceSubType, status, and diagnosticCode fields to classify the predominant failure mode. Isolate the spike to a configuration set, a sending domain, or a campaign segment. Rule out authentication before assuming list quality, because authentication failures can look identical to list problems in aggregate metrics. Check blocklist status when 5.7.1 codes dominate. Suppress immediately and pause sending if the rate is climbing toward the 5% review threshold. Then build the monitoring infrastructure so that the next spike becomes an alert you receive in minutes, not an enforcement notice you receive after the damage is done.

Never find out from AWS again
SES Monitor alerts you the moment bounces and complaints start arriving.
Start monitoring

Keep reading

All articles →
31 Aug 2026

Microsoft Outlook Bulk Sender Rules and Amazon SES

12 min read
28 Aug 2026

Amazon SES Tenants: Reputation Isolation for SaaS Senders

13 min read
25 Aug 2026

Engagement Signals: The SES Reputation Factor

14 min read

Start protecting your SES reputation today

Connect your AWS SES account in a couple of minutes and get bounce and complaint alerts before a problem becomes a suspension.

2-minute setup · No contracts · Cancel anytime