Skip to content
Moosewave
Delivery engineering

Amazon SES send pacing: make the queue respect the real allowance

Design SES send pacing around recipient quotas, rolling usage, shared capacity, bounded retries, useful expiry, and duplicate-safe dispatch decisions.

Moosewave6 min read
A yellow metronome stands beside pink envelopes on a short blue conveyor, suggesting controlled send pacing.

The short answer

A send queue should turn the provider’s current allowance into an explicit dispatch policy. Keep recipients, rolling usage, acceptance rate, retry authority, and message expiry visible together. More workers can increase attempted sends without increasing the number of requests the provider can responsibly accept.

The queue design below is an applied example, not a production configuration for every SES account. Read your actual region’s current sending limits and account status. Any arithmetic is illustrative, and provider acceptance remains different from delivery, inbox placement, or customer action.

  1. Use current recipient-based limits for the correct region.
  2. Coordinate workers instead of giving each its own imaginary allowance.
  3. Separate a retryable rejection from an uncertain previous acceptance.
  4. Expire work that is no longer useful or authorized.

1. Read the allowance that exists today

SES distinguishes a rolling 24-hour sending allowance and an acceptance rate, with quotas scoped by AWS Region and counted by recipients. The account’s current configuration matters; an example from a tutorial does not establish your production limit. The documented maximum acceptance rate is also not a promise that every request will be accepted at that pace in every moment.

Build a small account-capacity view that names the region, observed limit, recent accepted-recipient usage, refresh time, and health status. Mark stale information as stale. In our hypothetical service, receipts and campaigns share the same account allowance, so a campaign planner must consider both. A team should not schedule a large batch from an audience count alone and discover during dispatch that another process consumed the remaining capacity.

Reference: AWS: Managing SES sending limits

2. Give the workers one coordinated budget

A worker-local rate limit can multiply the intended pace when the service scales. If each of several workers believes it owns the full allowance, more replicas create a larger burst at exactly the moment a queue is under stress. Coordinate reservations through a shared mechanism appropriate to your deployment, and define how ownership expires if a worker disappears before the request completes.

Separate permission to attempt a request from evidence that a recipient was accepted. Record the reservation and the dispatch attempt without prematurely calling it a delivery. Keep the policy understandable to operators: what is shared, what is reserved for important flows, and which condition pauses new work? A high queue depth should trigger investigation or controlled pacing, not automatically remove the boundaries that protect the provider relationship and the recipient experience.

3. Classify failures before deciding to try again

A documented throttling rejection and a timeout after sending a request are different observations. The first can explain why a new attempt is needed; the second may leave uncertainty about whether the provider accepted the original. Do not replay an entire campaign because a worker lost its acknowledgement. Preserve attempt identity and use the supported reconciliation path before repeating an irreversible external action.

For retryable failures, use bounded backoff with jitter and an overall deadline. A retry should still pass the current recipient policy and useful-expiry check. If a queue is provided by a service with duplicate-delivery semantics, design handlers accordingly instead of treating receipt of a job as proof it has never run. The goal is a controlled attempt history with a clear next decision, not a claim of exactly-once email delivery built from optimistic queue behavior.

Reference: AWS: SQS at-least-once delivery

4. Let stale messages leave the queue

A flash-sale reminder that emerges after the offer closes is not a successful backlog recovery. Give each job a useful-until condition and re-check it before dispatch. An account message may have its own reason to expire or be replaced. Preserve why a job was canceled so the team can distinguish healthy expiry from an unexplained infrastructure failure.

Define priorities without starving lower-priority work forever. A queue that constantly accepts new urgent jobs while never advancing old valid jobs needs an explicit fairness or escalation policy. In our example, the operator can pause promotions while preserving a reviewed reserve for purchase confirmations. When capacity recovers, re-evaluate the promotion’s audience and facts. Do not use the old snapshot as authority to send a now-irrelevant message merely because it was once approved.

5. Measure pressure in terms an operator can act on

Show oldest valid job age, eligible backlog, reservations, accepted recipients, retry categories, and cancellations. Keep separate counters for prepared work and provider-accepted work. A queue that shrinks because jobs expired has not produced the same outcome as a queue that shrinks because useful messages were accepted. Make that distinction visible before presenting a single reassuring progress percentage.

Run a rehearsal with reduced capacity, multiple workers, a stale limit snapshot, and a simulated acknowledgement loss. Verify that no worker silently bypasses the shared budget and that the operator can tell which jobs need a decision. Keep the test isolated from production recipients. A stable queue is one whose behavior under pressure can be explained and controlled, not merely one that empties quickly under ideal laboratory conditions.

  • Current region and recipient allowances are explicit.
  • Worker scaling preserves the shared pacing policy.
  • Uncertain acceptance is not blindly retried.
  • Eligibility and useful expiry are checked at dispatch.
  • Pause, recovery, and escalation owners are named.

6. Keep campaign preparation independent from send authority

A template can be completed while the queue is paused. An agent can prepare drafts, report pressure, and propose a revised schedule without taking permission to send more mail. Bind any approval to the relevant message and audience revision, then re-check current conditions when the job becomes eligible. The queue’s recovery should not silently expand an agent’s authority.

Use a Moosewave template for the draft and this guide to describe the dispatch contract surrounding it. Keep the acceptance receipt, later provider events, and business outcome as separate records. That separation makes it easier to improve performance without improving the wrong number. A useful send-pacing design preserves recipient decisions and operational evidence while allowing legitimate work to move at a sustainable pace.

Frequently asked questions

Direct answers to the questions that matter before this change reaches real recipients.
Will more workers increase my SES sending quota?

No. More workers increase concurrency, not the account’s allowance. Coordinate pacing and check the current limits in the relevant AWS Region.

Should every timeout immediately retry?

No. A timeout can leave the previous request’s acceptance uncertain. Preserve attempt identity and reconcile when possible before risking a duplicate external effect.

Is an empty queue proof that all emails were delivered?

No. Jobs may have been accepted, canceled, expired, or failed. Report those outcomes separately and do not equate acceptance with inbox placement.

Primary sources checked for this guide

Sources checked 13 October 2026. Product behavior and documentation can change, so the linked primary source takes precedence if it differs from this article.

Share this article

From field note to next move

Turn the question into a reviewable plan.

Give Moosewave the outcome you want. The goal carries into a guided workspace with its scope, approval points, and evidence still attached.

Journal handoffGuided workspace · no live actions
Enter to preview · Shift + Enter for a new line

Opens a guided workspace. Nothing is sent or changed.

  1. 01UnderstandQuestion and evidence
  2. 02PlanScope and exclusions
  3. 03ApproveExact proposed action
  4. 04VerifyResult and receipt
From an operational question to a reviewed message

Make the message clear. Keep its operating contract intact.

Choose a Moosewave template, adapt the words to the reader’s task, and use these checks to review the sending and destination systems around it.