Sending & Deliverability

Sending Throttling Strategies in Senddera

Per-server, per-list, time-of-day throttling and adaptive backoff via SendingServer fields.

May 9, 2026·7 min read· Advanced

"Send everything as fast as possible" is the wrong policy. ISPs throttle senders that exceed reasonable per-hour and per-recipient rates; sustained bursts trip rate-limit detectors that erode reputation before they trip the more visible block. The best-deliverability senders pace consistently below the throttle threshold of every ISP they target — not because they need the slack, but because predictable cadence is itself a positive reputation signal.

This article covers the four throttling patterns Senddera supports, when each is appropriate, and the field-level configuration to implement them.

Pattern 1 — Per-server throttling

The simplest pattern: limit the rate at which a sending server emits messages. Senddera's SendingServer model has these fields:

Field Purpose
sending_quota Max messages per quota_period
quota_period One of: minute, hour, day, week, month
sending_quota_value (per second) Hard SMTP-rate ceiling — how fast the worker dispatches

Daily quota caps the total volume per server per day; per-second rate caps the burst. Configure both:

Admin → Sending Servers → <server> → Edit
   Sending quota:        500,000
   Quota period:          1 day
   Throttle (per second): 100      (= 360,000/hour ceiling, well under daily cap)

The interplay matters. With quota = 500k/day and throttle = 100/sec, the worker can drain the quota in ~83 minutes — too fast for some ISPs to digest cleanly. Spreading across the working day (target ~10/sec for a 500k/day program) gives Gmail/Microsoft adaptive throttle room to learn engagement before the next message arrives.

Pattern 2 — Per-list throttling (timing for engagement)

A list mailed all at once has a sharp engagement spike (everyone opens within 4 hours, then nothing). A list mailed over 8 hours has a flatter spike — opens spread, click-through is roughly 15-25 % higher, and the receiver-side spam filters see your traffic over a longer window which improves classification.

In Senddera:

Customers → <customer> → Campaigns → New → "Send Settings"
   Send rate: 10,000/hour    (the campaign's max throughput)
   Schedule: Best Time per Subscriber Timezone     (optional, see below)

The campaign's send rate is bounded by its sending-server's quota AND the campaign's own configured rate. Setting both gives you fine-grained control: a server might be capable of 100/sec, but you cap a particular campaign at 50/sec so it doesn't dominate the queue.

Pattern 3 — Time-of-day shaping

For B2C senders, send timing measurably affects opens. Senddera's "Send by recipient timezone" mode (controlled per subscriber via the timezone attribute):

Campaign → "Schedule by Subscriber Timezone"
   Window: 09:00 - 18:00 recipient local
   Use offset: subscriber.timezone (or list default)

The worker dispatches per-subscriber based on each recipient's local time. Implementation: Senddera computes the dispatch time per subscriber and queues the SES/Mailgun API call accordingly. This pattern shifts the daily peak from "your timezone 09:00" to "many smaller peaks distributed across all recipient timezones," which tends to flatten the throughput curve and reduce momentary throttling.

The cost: throughput is no longer "as fast as the worker can run" — it's gated by recipient-timezone-distribution. For a list mostly in 4 timezones, expect 4 distinct throughput peaks across 24 hours.

Pattern 4 — Adaptive backoff (auto-pause on signals)

Per the WarmupStrategy data model, Senddera can auto-pause sending when bounce or complaint thresholds are crossed:

// app/Dto/WarmupStrategyData.php — relevant fields
public bool $enableSafetyChecks;
public bool $pauseOnNegativeSignals;
public float $maxBounceRate;        // 0.05 = 5%
public float $maxComplaintRate;     // 0.003 = 0.3%

When pauseOnNegativeSignals is on and either rate is exceeded over the rolling window, the queue worker stops dispatching for the affected sending server until an admin un-pauses it. This is the safety system protecting reputation from a content disaster (a campaign that triggers a complaint storm).

Don't disable this. The cost of a 4-hour pause that prevents a 24-hour deliverability hit is a strict win.

Configuring the worker for sustained throughput

Two queue-worker tuning levers:

# /etc/supervisor/conf.d/Senddera-worker.conf
command=/usr/bin/php /var/www/Senddera/artisan queue:work \
    --sleep=3 --tries=3 --max-time=3600 \
    --memory=256
numprocs=4    # one process per ~25k/day; tune by tier

--max-time=3600 recycles the worker every hour to bound memory leaks; --memory=256 recycles when memory exceeds 256 MB (also leak protection). At Medium-tier and above, run more numprocs rather than longer-lived workers.

For SES sending, configure SES's own per-account rate limit at parity with Senddera's per-server rate — don't have Senddera dispatch faster than SES will accept; SES will start returning Throttling.Send errors that Senddera logs as failed jobs.

Throttle response to provider 421/4.7.0

When the SMTP transaction returns a 421 or 4.7.0 (rate-protected defer), Senddera's bounce handler logs a soft bounce. The Laravel queue retries the message after 5/15/60 minutes. For a single recipient this is fine; for many simultaneous recipients (a reputation event), you want to:

  1. Auto-pause the sending server (Pattern 4 will do this if bounce rate exceeds threshold).
  2. Reduce the per-second rate by 50 % when a 421 spike is detected.
  3. Resume at the reduced rate; bump back up only after 12 hours clean.

Senddera doesn't auto-implement step 2 (yet); you can do it manually via cron + an artisan command that polls bounce rate and updates sending_quota_value per server. For most ops, the pattern-4 auto-pause is sufficient.

Diagnostic queries

Throughput per sending-server-per-hour, last 24h:

SELECT
  ss.name,
  HOUR(tl.created_at) as hour,
  COUNT(*) as sends
FROM tracking_logs tl
JOIN sending_servers ss ON tl.sending_server_id = ss.id
WHERE tl.created_at > NOW() - INTERVAL 24 HOUR
GROUP BY ss.id, hour
ORDER BY ss.name, hour;

Find sending-servers approaching their per-day quota:

SELECT name, sending_quota,
  (SELECT COUNT(*) FROM tracking_logs
   WHERE sending_server_id = ss.id
     AND created_at > CURRENT_DATE) as today_sent
FROM sending_servers ss
WHERE quota_period = 'day'
ORDER BY today_sent / sending_quota DESC;

Alert when ≥ 90 % of any quota.

Related reading

FAQ

What's the right per-second rate?

Depends on tier and recipient distribution. Rules of thumb:

  • 50k/day program → 5/sec sustained
  • 500k/day program → 25-50/sec sustained
  • 5M/day program → 200-500/sec sustained, distributed across multiple sending servers

Below ~5/sec, throttling is overhead; above ~500/sec from a single IP, you're flirting with most ISPs' rate-protection.

Can I send faster on weekends when ISPs are quieter?

Marginally. ISP rate-protection is roughly the same 24/7. The actual constraint is recipient receipt timing — sending Saturday 02:00 produces poor open rates regardless of throughput.

What if my sending server's quota is "unlimited"?

You still want a per-second throttle. "Unlimited daily quota" with no per-second cap means a 1M-message campaign tries to send all 1M in the first minute, which trips every receiver's rate-protection.

Does throttling apply to API-based sending (SES, Mailgun)?

Yes. The per-second rate caps how fast Senddera makes API calls to SES/Mailgun. Exceeds the provider's account-level rate limit → API-level rate-limit errors → soft bounces in Senddera.

Throttle progression chart for new sending servers

When introducing a new sending server (warmup or capacity expansion), use this progression:

Phase Daily cap Per-second Spread (campaign duration) Acceptance
Day 1-2 100 1 Single 8-hour window during business day All sends accepted, 0 deferrals
Day 3-7 1,000 5 8-hour spread Bounce rate < 2 %, no soft-bounce burst
Week 2 10,000 20 12-hour spread covering 2 timezones SNDS GREEN, Postmaster appearing
Week 3 50,000 50 12-hour spread Postmaster IP rep ≥ Medium
Week 4+ 100,000+ 100+ Per recipient timezone (24h shaped) Postmaster IP rep High; full rotation

The "spread" column matters as much as the daily cap. A 50,000-message campaign sent in 2 hours from a fresh IP is dramatically worse for reputation than the same volume over 12 hours.

Reading the Senddera dashboard for throttle effectiveness

The per-server hourly graph (Admin → Sending Servers → → Stats) should show roughly flat hourly throughput during the campaign window. Spike patterns indicate problems:

  • Single tall spike at hour 0 — your throttle isn't working; messages are bursting from the worker.
  • Sawtooth pattern — workers are recycling rapidly, possibly due to memory limits. Bump --memory=512.
  • Plateau then sudden drop — you hit the daily quota mid-campaign; bump the quota or split across more servers.
  • Plateau with a dip mid-window — receiver-side throttling (often Microsoft RP-002). Investigate SNDS for the affected IP.

The healthy pattern is a flat rectangle. Hour-to-hour variance < 20 % means the throttle is doing its job.

Run your email marketing on your own server

Full source code, no subscriber tax, unlimited sending. One-time $74 license, lifetime updates.

Get Senddera — $74 one-time