Amazon SES Suppression List Explained

Isometric illustration of a teal pillar with a shield protecting against a cluster of suppressed email envelopes, with a purple filter funnel accent.

Amazon SES has two suppression lists: an account-level list you own that blocks hard bounces and complaints on every send from your AWS account in that region, and a global list AWS manages of confirmed bad addresses across the whole service that you cannot disable (AWS). The account-level list is enabled by default for any SES account created after November 25, 2019, and it is what keeps a single hard-bouncing address from pushing you toward the 5% pause threshold. This guide covers what each list does, how addresses land on them, the SES API v2 surface, and the production patterns Mailblast runs on top of the customer's own SES.

What the SES suppression list does

The Amazon SES account-level suppression list is a per-region block list that automatically prevents delivery to addresses that previously hard-bounced or generated a complaint on your account (AWS). When you call SendEmail to a suppressed address, SES accepts the request but does not attempt delivery, and the send does not count toward your Reputation.BounceRate or Reputation.ComplaintRate - which is what protects your account from sliding into review or pause.

Suppressed sends still count against your daily sending quota. Only hard bounces and complaints are auto-added; soft bounces (full mailbox, temporary DNS, greylisting) are never suppressed because they may resolve.

How the global suppression list differs

The global suppression list is a separate AWS-managed block list of email addresses that have hard-bounced from any SES customer across the service (AWS). It is on for every account and cannot be disabled. When you send to a globally-suppressed address SES returns an error and counts the attempt against your bounce rate, so the operational hygiene rule is to check addresses yourself before submitting them rather than relying on SES to filter them at send time.

The two lists answer different questions. Account-level: "has this address ever bounced or complained on my account?" Global: "is this address known dead across all of SES?" Removing an address from your account list does nothing to the global list, which is why a re-send to a confirmed dead address re-bounces.

Account-level vs configuration-set suppression

Account-level suppression applies to every send across the AWS account in the current region. Configuration-set suppression is an override layer attached to a named configuration set that can disable suppression entirely or change which reasons trigger it (AWS). The three valid override outcomes are: inherit account-level, disable all suppression for that config set, or apply a custom reason list of BOUNCE, COMPLAINT, or both for that config set.

Behavior Account-level Configuration-set
Default scope Entire AWS account in region Only sends tagged with that config set
Enabled by default (post-Nov 2019) ✓ Yes Inherits account
Override account settings ✗ N/A ✓ Yes
Configurable reasons BOUNCE, COMPLAINT, or both BOUNCE, COMPLAINT, both, or none
Typical use case Global safety net for the account Separate marketing vs transactional streams
API PutAccountSuppressionAttributes PutConfigurationSetSuppressionOptions
Source: AWS, Using the Amazon SES account-level suppression list.

A common pattern: keep account-level suppression enabled for BOUNCE COMPLAINT, then attach a transactional configuration set that overrides with BOUNCE only. That way a complaint on a password-reset email - which the user needs to receive - does not lock them out of their own account.

How addresses get on the list

Three paths add addresses to the account-level suppression list: automatic bounce or complaint events processed from SES feedback notifications, manual PutSuppressedDestination API calls, and bulk imports via CreateImportJob from an S3 source (AWS). On a mature production account the auto path dominates, which is why the hygiene work that pays off most is fixing the upstream collection problem, not auditing the API calls.

Typical sources of SES suppression list additions How addresses land on the SES suppression list Distribution on a mature production account, illustrative shares Auto hard bounces 75% Auto complaints (FBL) 15% Manual API additions 8% Bulk CSV imports 2% 0% 50% 100%
Illustrative distribution. Actual ratios vary by sending mix and list hygiene.

Automatic additions happen when SES processes a bounce or complaint notification that matches your enabled suppressed-reasons. The address is added with the corresponding reason (BOUNCE or COMPLAINT) and a LastUpdateTime timestamp. AWS also adds hard-bounced addresses to the global SES suppression list shared across the service.

Manual additions use PutSuppressedDestination and are the right tool when you receive an unsubscribe outside the SES feedback loop - for example, a reply to support saying "remove me." Push the address yourself with reason COMPLAINT so it is treated identically to a recipient-reported spam click. See our SNS feedback loop guide for wiring up the auto path.

Bulk imports use CreateImportJob with an S3 source file. AWS caps bulk add at 100,000 addresses per S3 object per API call, with a maximum of 20 concurrent import jobs.

Removing addresses from the suppression list

Remove an individual address with DeleteSuppressedDestination or a batch with CreateImportJob using action DELETE (AWS). Removal is appropriate in a narrow set of cases: you confirmed the address is valid out-of-band, the bounce was caused by a transient receiving-side outage now resolved, or the recipient explicitly asked to re-subscribe through your own opt-in flow.

The risk: AWS adds hard-bounced addresses to the SES global suppression list too. Removing from your account list does nothing to the global list, so a re-send to a confirmed dead address will bounce again, re-suppress, and burn another bounce-rate event. Treat removal as a deliberate operator action, not an automated step in your subscriber-management flow.

API patterns for suppression management

The five operations that cover day-to-day suppression management live in SES API v2: put-suppressed-destination to add, get-suppressed-destination to check, list-suppressed-destinations to page through, delete-suppressed-destination to remove, and put-account-suppression-attributes to change which reasons feed the account list (AWS). All examples below use the AWS CLI; the underlying SDK calls have the same shape.

Add a single address:

aws sesv2 put-suppressed-destination \
  --email-address user@example.com \
  --reason BOUNCE

Check whether a specific address is suppressed:

aws sesv2 get-suppressed-destination \
  --email-address user@example.com

The response includes Reason, LastUpdateTime, and (for auto-added entries) Attributes.FeedbackId linking back to the originating SES event.

List all suppressed addresses with date filtering:

aws sesv2 list-suppressed-destinations \
  --start-date 1722211200 \
  --end-date 1725004800

The response is paginated. AWS warns that you must follow NextToken to retrieve more than the first page - common gotcha for operators who think their list "is only a few hundred entries" because they read page one.

Remove an address:

aws sesv2 delete-suppressed-destination \
  --email-address user@example.com

Enable account-level suppression on a legacy account:

aws sesv2 put-account-suppression-attributes \
  --suppressed-reasons BOUNCE COMPLAINT

One case-sensitivity trap worth flagging: AWS stores addresses in the exact case received. User@Example.com and user@example.com are the same address for sending purposes but different keys for GetSuppressedDestination and DeleteSuppressedDestination. Normalise to lowercase before any management API call to avoid phantom "not found" errors.

Common production patterns

Three patterns show up repeatedly in well-run SES deployments: syncing suppression state to your own subscriber database via SNS, running separate configuration sets for marketing and transactional streams, and auditing fresh additions weekly. They are not mutually exclusive, and most mature accounts run all three because each one closes a different operational gap that the account-level list alone leaves open (AWS).

1. Sync suppression state to your subscriber database. Subscribe to SES bounce and complaint events via SNS, write the affected addresses to your own suppressions table, then mark the matching subscriber as unsubscribed_reason='hard_bounce'. This keeps your sending application from ever re-queueing the address and gives you analytics SES alone does not surface. See our bounce and complaint handling walkthrough for the SNS wiring.

2. Use separate configuration sets per stream. Attach a marketing configuration set with both BOUNCE and COMPLAINT suppression, and a transactional set with BOUNCE-only. A spam complaint on a marketing email correctly blocks future marketing, but a complaint on a one-off receipt email should not block that user's next password reset.

3. Audit the list weekly. Run list-suppressed-destinations --start-date for the prior 7 days and review the additions by reason. A sudden complaint spike often points to a single underperforming segment or list source you can quarantine before bounce rate becomes an account-pause issue. AWS pauses sending when Reputation.BounceRate crosses 5% or Reputation.ComplaintRate crosses 0.1%.

When Mailblast handles this for you

Running the patterns above is straightforward but it is also undifferentiated plumbing - the kind of code every BYO-SES team writes, debugs, and re-debugs. Mailblast sits on top of your own Amazon SES account and runs them as a managed layer: SNS topics for bounce and complaint events are provisioned automatically, hard bounces and complaints sync to subscriber lists in real time, and the management UI shows the unified suppression view across your SES regions and our subscriber model. Your SES account, your sending domain, your reputation - we just run the operator playbook so you do not have to. Mailblast's free plan includes 1,000 contacts and 10,000 emails per month with no automation sends; the first paid rung is $10/month for that same 1,000 contacts and adds automation.

FAQ

Is the Amazon SES suppression list enabled by default?

Yes. AWS documents that any SES account created after November 25, 2019 has the account-level suppression list enabled by default for both bounces and complaints. Older accounts must enable it explicitly with PutAccountSuppressionAttributes. The default behavior automatically blocks future sends to hard-bouncing or complaining addresses.

Does the SES suppression list catch soft bounces?

No. AWS states that only hard bounces are added to the account-level suppression list. Soft bounces (full mailbox, temporary DNS issues, greylisting) are not auto-suppressed because they may resolve. Your application should track soft bounces separately and apply its own retry-and-give-up policy after several consecutive failures.

Can I remove an address from the SES suppression list?

Yes, with DeleteSuppressedDestination in the SES API v2 or the console. AWS warns that suppressed addresses also land on the global suppression list, so even after removal a hard-bounce address will likely bounce again and re-suppress. Only remove addresses you have direct confirmation are valid.

How long does SES keep addresses on the suppression list?

Indefinitely while your account is active. AWS states addresses remain on the account-level list until you remove them. The one exception: if your account's sending ability is paused, SES automatically deletes the addresses after 90 days. Restoring sending before 90 days preserves the list.

What is the difference between account-level and configuration-set suppression?

Account-level applies to every send from the AWS account in that region. Configuration-set suppression overrides account-level for emails sent with that specific configuration set, letting you disable suppression entirely or apply different reasons (BOUNCE, COMPLAINT, or both) per sending stream - useful for separating transactional from marketing traffic.


Disclosure: Mailblast is a hosted management layer for your own Amazon SES account. The suppression lists belong to your AWS account; Mailblast wires up the SNS feedback path, syncs hard bounces and complaints to your subscriber lists, and surfaces a unified view across regions so the operator playbook runs without manual scripts.

Ready to Start Your Email Marketing Journey?

Join thousands of businesses using Mailblast to grow their audience.

← Back to Blog