Sequence state persisted per contact (survives restarts)
Why it matters
Sequence state held only in memory — a JavaScript Map, a module-level object, or a BullMQ job payload with no database mirror — is erased by any process restart, deployment, or crash. CWE-400 and CWE-693 both apply: the system is neither protected against state loss nor recoverable after failure (iso-25010:2011 reliability.recoverability). The concrete outcome: contacts re-enter sequences from step 0, receive duplicate emails, or disappear from sequences entirely. At scale, a single deployment during a live campaign can corrupt thousands of enrollment records with no recovery path short of manually reconstructing state from email send logs — if those logs even exist.
Severity rationale
Critical because in-memory state is permanently lost on any restart, causing duplicate sends or silent contact abandonment with no recovery path.
Remediation
Write enrollment state to the database before enqueuing the job — not after. If the enqueue fails, the persisted state serves as a recovery checkpoint; if the write fails, no job is created and nothing is lost.
// Always write state BEFORE enqueuing the job
await db.contactSequence.update({
where: { id: enrollmentId },
data: {
currentStepIndex: nextStepIndex,
nextScheduledAt: scheduledTime,
status: 'active'
}
})
// Enqueue after state is persisted — failure here is recoverable
await queue.add('send-sequence-step', { enrollmentId }, { delay: delayMs })
Verify that your schema has current_step_index, next_scheduled_at, and status columns on the enrollment table — never rely on reconstructing position from the email_sends log.
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
- cwe · CWE-400 — Uncontrolled Resource Consumption
- cwe · CWE-693 — Protection Mechanism Failure
- iso-25010:2011 · reliability.recoverability
Taxons
History
- 2026-04-18·v1.0.0·Initial import from campaign-orchestration-sequencing·automated