Google's 2024 bulk sender guidelines mandate that senders maintain complaint rates below 0.10% to avoid inbox filtering at Gmail — the platform receiving roughly one-third of all consumer email in the US. Complaint rates above 0.30% result in throttling or blocking. Without code that monitors this rate and fires an alert before crossing the threshold, the first indication of a problem is often a sharp drop in open rates, by which point Gmail's filtering is already active and may persist for days or weeks after the rate is corrected. The 0.08% early-warning threshold gives an action window before the hard limit is breached.
Medium because complaint rate spikes are frequently triggered by specific campaigns rather than systemic failures, and an alert at 0.08% gives time to pause the offending campaign before Gmail's 0.10% threshold triggers automatic filtering.
Compute complaint rate over a rolling 24-hour window and fire alerts at two thresholds — a warning at 0.08% (pre-threshold) and a critical at 0.10% (Google's hard limit). Run this check from a scheduled job or after each FBL event batch:
const COMPLAINT_RATE_WARNING = 0.0008 // 0.08%
const COMPLAINT_RATE_CRITICAL = 0.001 // 0.10%
export async function checkComplaintRate(domain: string): Promise<void> {
const since = new Date(Date.now() - 24 * 60 * 60 * 1000)
const [sent, complaints] = await Promise.all([
db.emailLog.count({ where: { fromDomain: domain, sentAt: { gte: since } } }),
db.complaintEvent.count({ where: { domain, receivedAt: { gte: since } } })
])
if (sent === 0) return
const rate = complaints / sent
if (rate >= COMPLAINT_RATE_CRITICAL) {
await sendAlert({ severity: 'critical', message: `Complaint rate ${(rate * 100).toFixed(3)}% for ${domain} — above Google's 0.1% limit` })
} else if (rate >= COMPLAINT_RATE_WARNING) {
await sendAlert({ severity: 'warning', message: `Complaint rate ${(rate * 100).toFixed(3)}% for ${domain} — approaching threshold` })
}
}
Persist the computed rate to DomainReputation.spamRate so the check feeds the trend graph alongside Postmaster Tools data.
ID: deliverability-engineering.warmup-reputation.complaint-rate-alerting
Severity: medium
What to look for: Count all alert threshold definitions for complaint rate. Search for code that computes complaint rate (number of spam complaints / number of emails sent) and triggers an alert or sends a notification when the rate exceeds a threshold. Look for constants named COMPLAINT_RATE_THRESHOLD, MAX_COMPLAINT_RATE, or similar. Google's bulk sender guidelines require complaint rates below 0.10% to avoid inbox filtering. Check if alerts fire at 0.08% or earlier (before crossing the hard limit).
Pass criteria: Code computes complaint rate over a rolling window. An alert or automated action fires when complaint rate exceeds 0.10% (ideally alerting at 0.08% as an early warning).
Fail criteria: No complaint rate monitoring or alerting exists. Complaint rates are only observable by manually reviewing ESP dashboards.
Skip (N/A) when: The project does not process FBL or complaint events from ESPs.
Detail on fail: "No complaint rate alerting configured — team would not know if complaint rate crossed Google's 0.1% threshold until inbox delivery degraded" or "Complaint events processed into DB but no alert threshold logic found"
Remediation: Compute and alert on complaint rate:
const COMPLAINT_RATE_WARNING = 0.0008 // 0.08% — early warning
const COMPLAINT_RATE_CRITICAL = 0.001 // 0.10% — Google's hard limit
export async function checkComplaintRate(
domain: string,
windowHours: number = 24
): Promise<void> {
const since = new Date(Date.now() - windowHours * 60 * 60 * 1000)
const [sent, complaints] = await Promise.all([
db.emailLog.count({ where: { fromDomain: domain, sentAt: { gte: since } } }),
db.complaintEvent.count({ where: { domain, receivedAt: { gte: since } } })
])
if (sent === 0) return
const rate = complaints / sent
if (rate >= COMPLAINT_RATE_CRITICAL) {
await sendAlert({
severity: 'critical',
message: `Complaint rate for ${domain} is ${(rate * 100).toFixed(3)}% — above Google's 0.1% threshold`,
action: 'Pause sending immediately and investigate campaign content'
})
} else if (rate >= COMPLAINT_RATE_WARNING) {
await sendAlert({
severity: 'warning',
message: `Complaint rate for ${domain} is ${(rate * 100).toFixed(3)}% — approaching threshold`,
action: 'Review recent campaigns for complaint patterns'
})
}
}