Minimum spacing enforced between emails to same contact
Why it matters
Without a minimum-spacing guard enforced at send time, a contact enrolled in two simultaneous sequences can receive back-to-back emails minutes apart. CAN-SPAM Act Sec. 5 does not set a specific inter-email minimum, but sending frequency that a recipient experiences as abusive constitutes a material compliance risk under GDPR Art. 6 (lawful basis) and ePrivacy Art. 13, both of which require that commercial communications reflect the consent and reasonable expectations of the recipient. Beyond regulatory exposure, rapid-fire emails generate spam complaints, damage sender reputation, and suppress deliverability across the entire sending domain — affecting all customers, not just the one who complained.
Severity rationale
Critical because absent send-time spacing enforcement, overlapping sequences produce back-to-back emails that trigger spam complaints, degrade sender reputation, and create GDPR Art-6 exposure.
Remediation
Add a last_email_sent_at timestamp to the contact record and check it in the send job handler — not at enrollment time. Defer rather than drop emails that arrive before the minimum gap.
async function sendSequenceStep(enrollmentId: string, stepId: string) {
const enrollment = await db.contactSequence.findUnique({
where: { id: enrollmentId }, include: { contact: true }
})
const contact = enrollment.contact
const MIN_SPACING_HOURS = 4
if (contact.lastEmailSentAt) {
const hoursSinceLast = (Date.now() - contact.lastEmailSentAt.getTime()) / (1000 * 60 * 60)
if (hoursSinceLast < MIN_SPACING_HOURS) {
const delayMs = (MIN_SPACING_HOURS - hoursSinceLast) * 60 * 60 * 1000
await queue.add('send-sequence-step', { enrollmentId, stepId }, { delay: delayMs })
return // Deferred — do not send now
}
}
await sendEmail(contact, step)
await db.contact.update({ where: { id: contact.id }, data: { lastEmailSentAt: new Date() } })
}
The guard must live in the job handler, not the enrollment path. Enrollment-time checks cannot account for emails sent by other sequences after enrollment.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Campaign Orchestration & Sequencing Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- external · CAN-SPAM-Act-2003-Sec5 — CAN-SPAM Act — prohibition on sending to addresses that have opted out
- gdpr · Art. 6 — GDPR Article 6 — Lawfulness of processing (consent/legitimate interest basis for email)
- eprivacy · Art. 13 — ePrivacy Directive Article 13 — unsolicited commercial communications
Taxons
History
- 2026-04-18·v1.0.0·Initial import from campaign-orchestration-sequencing·automated