State Diagram
Message States
Drop Reasons
When a message is dropped, thestatus_detail field contains the reason.
Executor Pipeline
The message executor processes queued messages through a 10-step pipeline.- Poll queue — Coordinator queries
QueuedTextMessagefor unclaimed messages older than 10 seconds, sorted by send time, in batches of up to 50,000 - Group by list — Messages are grouped by
sending_listfor per-list processing and rate limiting - Validate list — Check that the sending list exists and is in
activestatus; drop messages for inactive or missing lists - Billing preflight — Verify the account has valid billing (payment method, no payment failures, free tier limit not exceeded); back off retryable messages 5 minutes or drop after 60-minute TTL
- Claim messages — Atomically claim a batch of messages using a unique claim token to prevent duplicate processing across VMs
- Filter stale — Discard messages queued longer than 30 minutes (
STALE_THRESHOLD_MINUTES) - Filter blocked content — Run message body through the blocked words checker; drop matches with
BLOCKED_CONTENTstatus - Filter blocked contacts — Check recipients against
ListContactBlock(unsubscribed/blocked contacts); drop matches withCONTACT_BLOCKEDstatus - Send via provider — Submit messages to the list’s SMS provider in batches with per-list rate limiting (default 17,000 messages/min)
- Record results — Insert
RawMessagerecords, delete from queue, updateMessageSentstatus, and track billing (segments sent per account)
Webhook Events
Provider delivery reports update message status asynchronously after sending.The
sent state is set immediately when the provider accepts the message. Final delivery status arrives via webhook, typically within seconds.Timing
Next Steps
Data Model
Entity relationships
Compliance
Opt-out handling and TCPA