Per-campaign and per-ISP limits are only as safe as their configuration — a misconfigured campaign with no maxPerHour and a per-ISP limit set too high can still dispatch thousands of messages per minute if there is no outer bound. A global system rate limit is the circuit breaker: regardless of what any campaign or ISP limiter is configured to allow, the system as a whole cannot exceed this ceiling. This single control prevents a configuration error, a bug in rate limit logic, or a runaway queue worker from causing catastrophic volume spikes that would require weeks of reputation recovery.
Low because the global limit is a safety net that only matters when other rate controls are misconfigured or absent, but its absence means there is no backstop against cascading misconfiguration at other levels.
Implement the global rate limiter as the outermost layer all sends pass through, configurable via environment variable so it can be adjusted without deployment:
const GLOBAL_MAX_PER_MINUTE = parseInt(
process.env.EMAIL_GLOBAL_MAX_PER_MINUTE ?? '500'
)
const systemRateLimiter = new Bottleneck({
reservoir: GLOBAL_MAX_PER_MINUTE,
reservoirRefreshAmount: GLOBAL_MAX_PER_MINUTE,
reservoirRefreshInterval: 60_000,
})
// Every send in the system goes through this first
export async function scheduleEmail(job: EmailJob): Promise<void> {
await systemRateLimiter.schedule(() => sendWithThrottle(job))
}
Set EMAIL_GLOBAL_MAX_PER_MINUTE in your environment configuration (not hardcoded) and document the rationale for the chosen value. Add a monitoring hook that logs when the reservoir drops below 20% of capacity, signaling the system is approaching the ceiling.
ID: deliverability-engineering.sending-throttling.global-rate-limit
Severity: low
What to look for: Count all system-level rate limit definitions. Look for a global maximum send rate that acts as a circuit breaker for the entire system, independent of per-campaign or per-ISP limits. This is the "never exceed X emails per minute across all campaigns combined" guardrail. Check for constants like GLOBAL_MAX_SENDS_PER_MINUTE, SYSTEM_RATE_LIMIT, or equivalent. Also check if this limit is configurable via environment variable without code deployment.
Pass criteria: At least 1 global system-level rate limit exists and is enforced as the outer bound. The limit is configurable via environment variable. The system logs or alerts when the global limit is being approached.
Fail criteria: No global system rate limit exists — per-campaign and per-ISP limits are the only controls, leaving no safety net if those limits are misconfigured.
Skip (N/A) when: Sending is routed entirely through an ESP that enforces global account-level limits and the codebase has no control over raw throughput.
Detail on fail: "No global system rate limit configured — a misconfigured campaign could exceed safe sending thresholds without any system-level circuit breaker" or "Per-ISP limits exist but no aggregate system cap"
Remediation: Implement a global rate limiter as the outermost control:
// Environment-configurable global ceiling
const GLOBAL_MAX_PER_MINUTE = parseInt(process.env.EMAIL_GLOBAL_MAX_PER_MINUTE ?? '500')
const systemRateLimiter = new Bottleneck({
reservoir: GLOBAL_MAX_PER_MINUTE,
reservoirRefreshAmount: GLOBAL_MAX_PER_MINUTE,
reservoirRefreshInterval: 60_000, // 1 minute
})
// All sends go through this first, then per-ISP limiters
export async function scheduleEmail(job: EmailJob): Promise<void> {
await systemRateLimiter.schedule(() => sendWithThrottle(job))
}