How Sending Works
Broadcast sends three types of email. This page explains the order they go out in, how the hourly limit on each email server is shared between them, and what you see while email waits.
| Type | What it is | Example |
|---|---|---|
| Transactional emails | One email to one person, sent through the API | A login code, a password reset, a receipt |
| Sequences | Automated emails sent step by step to each enrolled subscriber | A welcome series |
| Broadcasts | One email sent to many subscribers at once | A newsletter |
Broadcast also sends a few emails of its own through your servers, such as opt-in confirmation emails and test sends.
The priority order
The three types always go out in this order:
- Transactional emails
- Sequences
- Broadcasts
The order applies in two places: the job workers, and the hourly limit.
Job workers
Broadcast sends email from background jobs. When several jobs wait, a worker takes the job with the highest priority first. So a transactional email waits for no sequence step or broadcast job, and a sequence step waits for no broadcast job.
A worker that already runs a long broadcast job does not stop for a new job. For that reason, Broadcast also keeps one worker thread for transactional email only. Nothing else runs on that thread, so a login code never waits for a free worker, even when every other worker is busy with broadcasts. In our test, with every other worker thread busy with broadcasts, a login code went out in under a second. [build: confirm the number before publishing]
This extra thread runs in its own process in the job container, on top of JOB_CONCURRENCY. You do not need to set anything. Count it in your memory budget like a job process: it usually uses about 300 MB. The other workers run three threads per process. See Performance Tuning for JOB_CONCURRENCY.
The hourly limit
The order also decides how the hourly limit of a server is shared. See “Room kept for higher-priority email” below.
The hourly limit
Each email server has an emails per hour limit. The default is 200. The lowest value you can set is 15. Set it in Settings → Email Servers.
- The limit applies to one email server. Two servers have two separate limits.
- The hour is a rolling window: Broadcast counts the emails the server sent in the last 60 minutes. An email leaves the count exactly one hour after it was sent.
- Every email that Broadcast sends through the server counts: broadcasts, sequence steps, transactional emails, opt-in confirmation emails and test sends.
- Reset rate limit on the server page starts the count over. See “Reset rate limit” below.
Broadcast never sends above the limit. It holds email that does not fit, and sends it when the hour has room again.
Room kept for higher-priority email
On a server that sends more than one type of email, the lower-priority types stop before the full limit. The room above them is kept for the types that come first. A server keeps room only for the email types it sends. Choose the types on the server’s form under Email Types.
| The server sends | Broadcasts stop at | Sequences stop at | Transactional emails stop at |
|---|---|---|---|
| Broadcasts, sequences and transactional emails | 80% | 90% | 100% |
| Broadcasts and transactional emails | 90% | 100% | |
| Broadcasts and sequences | 90% | 100% | |
| Sequences and transactional emails | 90% | 100% | |
| One type only | 100% | 100% | 100% |
For example, a server with the default limit of 200 emails per hour that sends all three types:
- Broadcasts send up to 160 emails in the hour.
- Sequences send up to 180. So at least 20 are kept for sequences.
- Transactional emails send up to 200. So at least 20 more are kept for transactional email.
The numbers are rounded down. The server’s form and its detail page show the numbers for your limit, under “At this limit:”.
A server that sends only broadcasts keeps no room, so broadcasts can use the full limit. A server that sends only transactional emails and sequences keeps its whole limit for them. This is why we recommend separate servers. See Email Server Rate Limits.
Opt-in confirmation emails and test sends do not use this table. They send while the server is below its full limit.
How a broadcast is sent
When the broadcast fits
When you send a broadcast, Broadcast checks the room that broadcasts have left on the server this hour. A broadcast that fits sends at full speed. Small broadcasts are not slowed down.
When the broadcast is larger than the room
A broadcast that is larger than the room left sends as many emails as fit. Then it stops and waits. While it waits:
- It does not hold a worker. The workers are free for other email.
- Broadcast works out when enough old emails leave the hourly window, and schedules the next part for that time.
- At that time, the broadcast continues by itself. It sends what fits again, and repeats until everyone has it.
A broadcast that waits stays in the Sending status. It is not stalled, and you do not need to do anything.
For example, at a limit of 200 on a server that sends all three types, a broadcast to 1,000 subscribers sends 160 emails. Then it sends more as the first emails leave the hourly window, about 160 each hour, until all 1,000 have it.
Several broadcasts on one server
Two broadcasts that send through the same server share its room. Together they never go above the limit for broadcasts. If the first broadcast uses all the room, the second one waits for room too.
No move to another server
If a server is full, its email waits for room on that server. Broadcast does not move it to another server, even when the channel has one with room. Plan one server for each email type, with a limit that fits that type.
Parallel sending
With parallel sending on (PARALLEL_BROADCAST_SENDING=true), a broadcast is split into batches. A batch that runs out of room stops, stays open, and continues by itself when room frees up. The broadcast.batch_completed webhook event for that run has the outcome stopped. The run that sends the rest sends its own event, with completed when it finishes the batch. See Webhooks.
What you see while a broadcast waits
On the broadcast’s page:
- A blue banner says Waiting for room on the email server, with this text: “The server’s hourly limit is used up for broadcasts. Sending continues by itself at (time). To send sooner, raise the limit or reset the rate limit on the server page.”
- The Velocity card shows Waiting and Next send at (time), instead of a rate.
- The “Sending appears stalled” warning does not show while a broadcast waits for room.
On the email server’s page, under Rate Limiting, each broadcast that waits on that server is listed: “(name) is waiting for room until (time)”.
Pause and Resume
Pause
When you click Pause, the status changes to Paused at once.
A sending job checks the status about four times each second. So a few emails that were already on their way when you clicked may still go out. At full speed this is at most about 8 emails. A broadcast that waits for room sends nothing more. For a short time after a pause, the page says: “Emails that were already on their way when you paused may still arrive. The recipient count stops in a moment.”
A paused broadcast gets no more sends. This is also true for a part that was already scheduled for later: it finds the broadcast paused and stops.
Resume
Resume continues where the broadcast stopped. Nobody gets the email twice. If the server has no room for broadcasts, the broadcast waits for room again, as described above.
Reliability
Each recipient gets a broadcast at most once
Just before Broadcast hands an email to the provider, it records that this recipient’s send has started. Every later attempt checks that record first. If the record exists, the attempt does not send again. So a restart, a retry or a second job cannot send a duplicate.
If a send fails with an error, Broadcast removes the record, so the email can be tried again or marked as failed.
After a crash or a deploy
A broadcast that was sending when the job container stopped continues by itself when the container is back. It continues from where it stopped and does not start over. The recipients that were already mailed are not mailed again.
A wait for room is safe in the same way. A broadcast that waits for room has not started any send, so a restart while it waits leaves nothing half done.
Transactional email when the server is full
Transactional email stops only at 100% of the limit. On a server that also sends broadcasts or sequences, those stop first, so transactional email still has room.
If the server is at its full limit, a transactional email waits:
- Broadcast tries to send it again every minute. The email stays Queued.
- At the first wait, Broadcast sends the
email.send_delayedwebhook event. This is notemail.delivery_delayed, which means the provider accepted the email and the recipient’s mail server delays it. - After 30 minutes of waiting, every page of the channel shows a notice: “1 transactional email has been waiting for room on the email server for over 30 minutes”, with View transactional emails.
- After 24 hours, Broadcast stops trying. The email is marked Failed with the reason “Email server at hourly limit: no room for 24 hours, giving up”. Broadcast sends the
email.failedwebhook event and logs aRate Limiterror. Every page of the channel shows a red notice for 24 hours: “1 transactional email failed in the last 24 hours because the email server stayed at its hourly limit for 24 hours”.
As soon as there is room, the email sends and the wait ends.
Sequences when the server is full
When a server has no room for sequences, a sequence step waits:
- It tries again in one minute, and every minute after that, until there is room.
- The wait is not a failed attempt. It does not count toward the step’s failures, and it does not send
email.failed. - On the sequence’s list of subscribers, the enrollment shows “Waiting for room on the email server since (time)” under its step.
When room frees up, the step sends and the enrollment continues as normal.
Reset rate limit
Reset rate limit is on the email server’s page, under Rate Limiting. You are asked to confirm.
A reset starts the hourly count over from now. Only emails sent after the reset count toward the limit. Your send history is not changed.
Broadcasts that wait for room on that server continue at once. You do not need to wait for their next scheduled time. Waiting transactional emails and sequence steps send at their next one-minute retry.
A reset does not raise the limit, and it does not change your provider’s own limits. If you reset often, raise the server’s emails per hour value instead.
Upgrading to 2.43.0
Warning
Pause any broadcast that is sending before you upgrade. This release changes how a broadcast waits at the hourly limit. A paused broadcast moves to the new way when you resume it. Resume the broadcast after the upgrade.
[build: add the version number, and add the same callout to Upgrading]
Practical advice
- Use separate servers. Use one server for broadcasts, and a separate server for transactional emails and sequences. Then a newsletter never uses the room your login codes need, and complaints about a newsletter do not affect your login codes. See Email Server Rate Limits.
- Set the limit to your provider’s real quota. A limit that is too low makes broadcasts slow for no reason. A limit that is too high lets the provider refuse or throttle your email. Check the hourly or daily sending quota in your provider account.
- Plan for the reserve. On a server that sends all three types, broadcasts get 80% of the limit. The server form shows the rate your list needs to finish a broadcast in 24 hours, and allows for this share.
- If login codes or other transactional emails are late:
- Open the transactional email and check its status. Queued with a wait notice means the server is at its full limit.
- To send now, click Reset rate limit on the server’s page.
- To stop it from happening again, raise the server’s limit, or move transactional email to its own server.
FAQ
Why did my large broadcast stop at 160?
Your server has a limit of 200 per hour and sends all three email types. Broadcasts stop at 80% of the limit, which is 160. The other 40 are kept for sequences and transactional email. The broadcast continues by itself as room frees up. To use the full limit for broadcasts, send them from a server that sends only broadcasts.
My broadcast shows “Waiting”. Is it stuck?
No. It used the room it has this hour, and it continues by itself at the time on the Next send at line. To send sooner, raise the server’s limit or click Reset rate limit on the server’s page.
Why did a few emails go out after I pressed Pause?
Those emails were already on their way. A sending job checks the status about four times each second, so up to about 8 emails can follow a pause at full speed. The status changes to Paused at once, and the broadcast sends nothing more after that.
Will Resume send the email twice to anyone?
No. Resume continues where the broadcast stopped. Broadcast records each recipient’s send before it hands the email over, and never sends to a recipient twice.
Why is my welcome email late?
A welcome email is usually a sequence step. If the server has no room for sequences this hour, the step waits and tries again every minute. The enrollment shows “Waiting for room on the email server since (time)”. This happens when a broadcast and your sequences share a server near its limit. Move your sequences to a separate server, or raise the limit.
Why did a transactional email fail with “server at hourly limit”?
The server stayed at its full hourly limit for 24 hours, so Broadcast stopped trying. Check the server’s limit. If transactional email shares a server with broadcasts, give it its own server.
What is the difference between email.send_delayed and email.delivery_delayed?
email.send_delayed means Broadcast has not sent the email yet, because the server is at its hourly limit. email.delivery_delayed means the provider accepted the email, and the recipient’s mail server delays it.
Does a full server send my email through another server?
No. Email waits for room on its own server. Use one server for each email type, with a limit that fits that type.