Configurable intervals
Each campaign defines its own bump_intervals array — for example [24, 48, 96] means bump after 1 day, then 2 days, then 4 days. The platform enforces minimum hours between each touch.
How it works: How it works: max_bumps is derived from array length. A 3-item array means 3 bumps maximum — no separate field to keep in sync.
Business hours enforcement
Bumps only fire within configured business hours and timezone. The scheduler checks eligibility before enqueuing — contacts are never messaged at 2am because a job happened to run then.
How it works: Timezone-aware: multi-segment hour strings supported. Configure different windows for weekdays and weekends per campaign.
Burst traffic handling
All scheduler eligibility queries use FOR UPDATE SKIP LOCKED — multiple workers can run simultaneously without processing the same conversation twice, even under heavy load.
How it works: Queue-backed: Redis + RQ absorbs burst traffic. Worker restarts don't lose queued jobs — all state is persisted in PostgreSQL.
Automatic retry on failure
If an outbound send fails, the platform retries at 60 seconds, then 300 seconds. After three failed attempts, the turn is flagged for operator review — no silent failures.
How it works: Idempotent by design: MessageSid is checked before every send. A recovered worker can never send the same message twice.