AWS SES production access denied? What AWS actually wants

AWS rejects SES production access requests with 'for security purposes, we are unable to provide specific details.' Here is what that means, what the reviewer is really checking, the application wording that works, and what to do after a second denial.

You filled in the form, described your use case, and waited a day. Then this arrived:

Thank you for submitting your request to increase your sending limits. We are unable to grant your request at this time. For security purposes, we are unable to provide specific details.

That last sentence is why you are reading this. AWS will not tell you what went wrong, and the request form gives you no obvious second move. Thousands of people hit this every month, and most of them either give up on SES or start guessing.

This guide is the thing nobody wrote: what the denial actually means, what the reviewer is checking, how to write an application that passes, and what to do if you have already been denied once or twice.

What the denial actually means

The first thing to understand is that the message is a template. It is sent verbatim to everyone. It is not a description of your specific failure, and reading it closely for clues will not help you — there are none in there.

The second thing is that “for security purposes” does not mean AWS suspects you of anything. It means AWS will not publish its review criteria, because a published checklist is a checklist spammers would optimize against. The vagueness is deliberate and it is not personal.

What the denial does tell you is this: the reviewer could not satisfy themselves that you have a legitimate list and a working plan for bounces and complaints. That is the whole test. Almost every rejection comes down to an application that did not make those two things verifiable.

It helps to understand what AWS is protecting. SES sends from shared IP pools. Your sending reputation is partly Amazon’s sending reputation. A new account asking for production access is asking Amazon to lend you its standing with every mailbox provider on the internet, on the strength of a form. They are not being obstructive; they are being asked for something valuable.

What AWS is actually checking

Four things, in roughly this order of weight.

1. Where your addresses come from, described concretely. “Users sign up on our website” is not an answer — it is a category. An answer is: “Addresses are collected through a signup form at example.com/subscribe. Every address receives a confirmation email and is only added to the sending list after the recipient clicks the confirmation link. We do not purchase, rent, scrape or import third-party lists.”

The word “confirmation” is doing real work in that sentence. Double opt-in is the single strongest signal you can give, because it is the one thing a spammer will not do.

2. How people stop receiving your email. The reviewer wants to know that unsubscribing is automatic and immediate, not a support ticket. Say that every message contains an unsubscribe link, that it is processed programmatically, that it takes effect immediately, and — if this is true — that you implement one-click unsubscribe per RFC 8058.

3. How you handle bounces and complaints. This is where most applications quietly fail. You need to describe a mechanism, not an intention. “We monitor bounces” is an intention. “Bounce and complaint notifications are delivered to SNS topics subscribed to our application endpoint, which adds the address to a suppression list; suppressed addresses are excluded from all future sends” is a mechanism.

Critically, you should have this already built when you apply. More on that below, because it is the highest-leverage thing in this guide.

4. Whether your described volume and your described business are consistent. If you are a two-person SaaS asking to send two million emails a month, explain why. If you are sending transactional email only, say so and give a realistic daily figure. Inflated numbers do not make you look established; they make the application look implausible, and implausible is the thing that gets denied.

Wire up SNS bounce and complaint handling before you apply

This is the step almost everyone skips, and it is the one that changes outcomes most.

The reason is simple: it converts every claim in your application from a promise into a description of something that already exists. The reviewer is trying to assess risk with very little information. An applicant who already has bounce plumbing in place is an applicant who has thought about the problem.

Practically, that means, before you submit:

  1. Create an SES configuration set and use it for your sends. This is what lets you route event notifications.
  2. Create SNS topics for bounces and complaints — separate topics make the handling code clearer, though one will do.
  3. Attach the topics to your configuration set as event destinations for the Bounce and Complaint event types. Add Delivery too if you want delivery confirmation in your logs.
  4. Subscribe an endpoint — an HTTPS endpoint, a Lambda, or SQS — that receives the notifications and writes the address to a suppression list.
  5. Actually suppress on send. A suppression list you never check is worse than none, because it gives you false confidence. Every send path must filter against it.
  6. Check the account-level suppression list in the SES console and enable both BOUNCE and COMPLAINT reasons if they are not already set. It is a setting, not a default you can rely on.
  7. Verify a domain with DKIM and publish the three CNAME records. Add a DMARC record while you are in the DNS console. None of this is strictly required for the application, but a domain with proper authentication reads as a real sender.

Then, in your application, describe what you built. You are no longer asking to be trusted; you are reporting a configuration.

A note on the account-level suppression list. This is a separate thing from the global suppression list AWS maintains across all of SES, and it is worth getting right before you apply. The account-level list is a setting: you enable it and choose which reasons it records, BOUNCE, COMPLAINT, or both. Newer accounts often have it switched on already, but do not assume — check it in the SES console under Suppression list, and enable both reasons if they are not set. It is still not a substitute for your own suppression list, because it does not know about the addresses that a specific client asked to be removed from a specific list.

Wording that works

Here is the shape of an application that passes. Every sentence in it must be true of your actual system — the point is not the phrasing, it is that the phrasing forces you to have built the thing. If a paragraph below is not true for you, the fix is to go and make it true, not to keep the sentence.

Use case. We send transactional email for [product], a [one-line description of what it does] used by approximately [N] customers. Messages are password resets, receipts, and account notifications triggered by a user action. We also send a weekly product newsletter to users who have explicitly opted in.

How we collect addresses. Transactional recipients are our own registered users, who provide an address at signup and confirm it by clicking a verification link before the account is activated. Newsletter recipients opt in separately, through a checkbox that is unticked by default, and receive a confirmation email; they are added to the list only after clicking the confirmation link. We do not purchase, rent, scrape, or import third-party lists, and we do not send to addresses we have not collected ourselves.

Unsubscribes. Every marketing message includes an unsubscribe link and a List-Unsubscribe header supporting one-click unsubscribe per RFC 8058. Unsubscribes are processed programmatically and take effect immediately; there is no manual step and no support ticket. Transactional messages are limited to messages the recipient’s own action triggered.

Bounces and complaints. We have configured an SES configuration set with SNS event destinations for bounce and complaint notifications. These are delivered to an endpoint that adds the address to our suppression list, which every send path is filtered against. Hard bounces and complaints are suppressed permanently and automatically. We monitor our bounce and complaint rates in the SES console and treat sustained increases as an incident.

Volume. We expect approximately [N] emails per day at launch, rising to roughly [N] within [timeframe]. Our sending domain [example.com] is verified with DKIM, and we publish a DMARC policy.

Some specific advice on tone. Write it as prose, in complete sentences. Be concrete about numbers, mechanisms and URLs. Do not pad it — a short application that answers all four questions beats a long one that circles them. And do not describe features you have not built, because if your bounce rate later suggests otherwise, that is a much worse conversation.

If you are running email infrastructure you deployed yourself, this is the point where the plumbing either exists or does not. Selva Mail wires up the SNS bounce and complaint topics, the suppression list and the RFC 8058 unsubscribe header as part of its deploy, which means the paragraphs above describe your setup on day one rather than a project you still have to do.

The region-retry strategy, honestly

You will find advice online telling you to request production access in a different AWS region if you are denied. This works often enough that it is worth understanding — and it is misunderstood often enough to be worth a warning.

Production access is granted per region. Reviews are handled by different queues, and there is a human element, so the same application can genuinely get different outcomes in us-east-1 and eu-west-1.

That said:

  • It is legitimate when your first application was fine and you got an inconsistent review. It is not a workaround for an application that did not answer the four questions.
  • Fix the application first. Retrying an unchanged application in a new region mostly buys you a second denial and a thinner-looking account history.
  • Choose the region you actually want. Sending from a region far from your users adds latency, and moving later means re-verifying identities and re-approving access. Pick on merit.
  • Do not fire off requests in six regions at once. It reads exactly like what it looks like.

After a second denial

A second denial means the application is not the problem you think it is. Change something real before applying again.

Re-read your application as a stranger. The most common failure is describing intentions in the passive voice — “bounces are monitored”, “users are able to unsubscribe”. Rewrite every such sentence to name the mechanism and the thing that runs it.

Check whether you actually have the plumbing. Send a test message to the SES mailbox simulator addresses (bounce@simulator.amazonses.com and complaint@simulator.amazonses.com) and confirm the address lands in your suppression list without you touching anything. If it does not, you have found the problem, and it is a good one to find — it would have hurt you in production anyway.

Reduce what you are asking for. A request for a modest daily volume from a plainly described business is easier to approve than a large one. You can request increases later, and an account with a clean sending history gets them easily.

Reply to the case rather than opening a new one. The support case from your denial can be reopened. Adding detail there — with specifics of what you have built since — gives the reviewer context that a fresh, identical-looking request does not.

Escalate through support if you have a plan. On a paid support plan you can ask for the case to be reviewed by someone who can discuss it. This is far more productive once you have made concrete changes, and not productive at all before then.

Consider whether the sending model is the real issue. Some use cases will not be approved, and no wording changes that: sending on behalf of addresses you did not collect, forwarding mail you received, mailing a list you acquired with a purchase, or any arrangement where the recipient never agreed to hear from you specifically. If that describes your case, the answer is not a better application — it is a different sending model.

Once you are approved

Production access is the beginning, not the finish line. AWS can and does put accounts back under review.

Watch the two numbers in the SES console that matter: bounce rate and complaint rate. AWS starts paying attention around 5% bounces and 0.1% complaints. Both are lagging indicators of list quality, so react to a trend rather than waiting for a threshold.

Beyond that, the habits that keep a sending domain healthy are the ordinary ones: never send to an address that hard-bounced, honor unsubscribes instantly, keep transactional and marketing traffic separated so a campaign cannot damage delivery of password resets, and re-engage or drop addresses that have not opened anything in months. Grading contacts on engagement and simply not mailing the dead ones is the cheapest deliverability work available.

None of that is exotic. It is just the part that has to be true before the application is worth writing.

Stop paying for the same contacts
every month.

$497 once. Runs on your infrastructure, sends through your own AWS SES account. Launch buyers get agency rights permanently — unlimited client workspaces. First 100 licenses.

or email us directly — hi@selva.run