Broadcasts
Broadcasts are one-time mass emails sent to a targeted audience. Use them for newsletters, announcements, promotions, or any communication that should go out to a group of contacts at once.
Broadcast Lifecycle
| Status | Description |
|---|---|
draft | Being composed. Nothing is sent. |
scheduled | Locked in with a future send date. The sweeper will pick it up when the time arrives. |
sending | The user clicked "Send Now". The sweeper will process it on its next run. |
processing | Currently being sent by the sweeper (locked to prevent double-sends). |
sent | Successfully dispatched. The sent_count and sent_at fields are populated. |
failed | A fatal error occurred during processing. The error_message field contains diagnostics. |
Audience Targeting
Broadcasts support flexible audience selection using a combination of include and exclude filters:
Include Filters
- Target Tags — Send to all contacts who have any of the selected tags.
- Target Events — Send to all contacts registered for any of the selected events.
- Target All Contacts — Send to every subscribed contact in the workspace (ignores tag/event filters).
Exclude Filters
- Exclude Tags — Remove contacts who have any of the excluded tags.
- Exclude Events — Remove contacts registered for any of the excluded events.
Audience Calculation Pipeline
The sweeper calculates the final recipient list in this order:
- Build the base audience from include filters (tags, events, or all contacts)
- Remove excluded contacts based on exclude tags and events
- Remove unsubscribed contacts (
is_subscribed = falseorunsubscribed_atis set) - Remove suppressed contacts (any active
contact_suppressionrecord) - Remove duplicates (a contact matching multiple include filters is only sent one email)
Suppressed contacts are still logged in the
email_sendstable with statussuppressedfor transparency and reporting.
Sending Process
The broadcast sweeper runs as a CRON job and:
- Finds ready broadcasts — either
sending(user clicked "Send Now") orscheduledwithscheduled_for ≤ NOW(). - Locks — Atomically sets status to
processingto prevent double-sends from concurrent workers. - Resolves the sender identity — Uses the broadcast's configured sender, or falls back to the workspace default.
- Calculates the audience — Applies all include/exclude filters and suppression checks.
- Personalizes — Resolves merge fields for each recipient's email.
- Sends in batches — Dispatches via the Resend Batch API in chunks of 100 emails.
- Logs — Records each send in
email_sendswith idempotent upserts (safe for retries). - Finalizes — Updates the broadcast status to
sentwithsent_countandsent_at.
Error Handling
- If a batch of 100 fails, the sweeper continues to the next batch rather than aborting the entire broadcast.
- If a fatal error occurs after locking, the broadcast is marked as
failedwith a diagnosticerror_messageso it doesn't get stuck inprocessingforever.
Scheduling
To schedule a broadcast for future delivery:
- Compose your email and select your audience
- Set the Scheduled For date and time
- Click Schedule
The broadcast status changes to scheduled. The sweeper will automatically pick it up and send it when the scheduled time arrives. You can cancel a scheduled broadcast at any time before it's processed.
Email Tracking
Every broadcast email is individually tracked in the email_sends table. Status progression:
sent → delivered → opened → clickedThese status updates are received via Resend webhooks and stored automatically.