# How Sending Works

> How Broadcast sends broadcasts, sequences and transactional email. Priority order, the hourly limit and its reserve, pacing, Pause and Resume, retries, and what to do when email is late.

Source: https://sendbroadcast.net/docs/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:

1. Transactional emails
2. Sequences
3. 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](https://sendbroadcast.net/docs/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](https://sendbroadcast.net/docs/email-server-rate-limits#use-a-separate-server-for-broadcasts).

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](https://sendbroadcast.net/docs/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:

1. Broadcast tries to send it again every minute. The email stays **Queued**.
2. At the first wait, Broadcast sends the `email.send_delayed` webhook event. This is not `email.delivery_delayed`, which means the provider accepted the email and the recipient's mail server delays it.
3. 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**.
4. 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.failed` webhook event and logs a `Rate Limit` error. 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](https://sendbroadcast.net/docs/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](https://sendbroadcast.net/docs/email-server-rate-limits#use-a-separate-server-for-broadcasts).
- **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:**
  1. Open the transactional email and check its status. **Queued** with a wait notice means the server is at its full limit.
  2. To send now, click **Reset rate limit** on the server's page.
  3. 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.
