# Campaign Sending Speed

# How Campaign Sending Works — Speed, Pacing & Retries

> A plain-English guide to *why* a campaign sends at the speed it does, what the words on the
> dashboard mean (Sent, Retrying, Queued, Failed), and which dials make it faster — with lots of
> everyday examples. No technical background needed.

> **TL;DR**
>
> * A campaign does **not** send all messages at once. It releases them in a controlled stream so WhatsApp doesn't block you.
> * Three dials control the speed: **how many sends run at the same time** (concurrency), **how often a new send is started** (send delay), and **how many a number may send each minute** (per-minute cap).
> * The slowest dial always wins — speeding up one dial does nothing if another is still the bottleneck.
> * **"Retrying"** means WhatsApp temporarily refused the message (usually a marketing limit) and we'll try again later. It is **not** stuck — and sending faster won't fix it.
> * **"Queued"** means waiting for its first try. **"Sent"** means WhatsApp accepted it. **"Failed"** means it gave up after all retries.

***

## 1. Why a campaign doesn't send everything at once

If you have 20,000 recipients, it would be lovely to fire all 20,000 messages in one second. But WhatsApp
won't allow it — every WhatsApp number has speed limits, and if you blast past them WhatsApp **throttles
you** (slows or blocks your messages) and can **lower your number's quality rating**, which hurts *every*
future campaign.

So instead of one big blast, Lodgestory sends in a **steady, paced stream** — fast enough to get through a
big list in a reasonable time, slow enough to stay on WhatsApp's good side.

Think of it like a call centre making outbound calls. You don't dial 20,000 people at once. You have a team
of agents, each dialling one person at a time, working steadily through the list. **Campaign sending works
exactly like a call centre** — and that one picture explains everything below.

***

## 2. The three dials (the call-centre picture)

| Dial               | Call-centre meaning                                       | What it controls                                          |
| ------------------ | --------------------------------------------------------- | --------------------------------------------------------- |
| **Concurrency**    | How many **agents** you have                              | How many messages can be *in progress at the same moment* |
| **Send delay**     | A rule: *"start a new call every X milliseconds"*         | How *often* a new message is launched (the launch rate)   |
| **Per-minute cap** | *"no more than N calls per minute, then take a breather"* | The maximum a single number sends in one minute           |

Let's take them one at a time, in everyday terms.

### Concurrency — how many agents

Each message takes **about 1–2 seconds** to send (that's how long WhatsApp takes to answer "got it").
Concurrency is how many of those can be happening **at the same time**.

* Concurrency of 1 = one agent. They send a message, wait \~1.5s for the reply, then send the next. Slow.
* Concurrency of 15 = fifteen agents all working at once. Roughly 15× faster.

> 🟢 **Everyday example.** One cashier vs. fifteen cashiers at a supermarket. Fifteen checkout lanes clear
>
> the queue far faster than one — but only if there are enough customers (messages) to fill them.

> ⚠️ **These agents are shared across the whole system — not per campaign.** All campaigns sending at the
>
> same time draw from the *same* pool of agents, so several at once means each gets a slice, not the full
> set. See [Section 5: What happens when several campaigns run at once](#5-what-happens-when-several-campaigns-run-at-once).

### Send delay — how often a new send starts

Even with lots of agents, we don't let them all dial at the *exact* same instant — that would look like a
spike to WhatsApp. Instead there's a small gap between each launch. Today that gap is **100 milliseconds**
(a tenth of a second) for WhatsApp Official.

* 100 ms gap → at most **10 new sends started per second**.
* 50 ms gap → at most **20 per second**.
* 20 ms gap → at most **50 per second**.

> ⚠️ **Important — this is the most misunderstood part.** The send delay starts **one** message each time,
>
> not a batch. "100 ms delay" means *one new message every 100 ms*, i.e. 10 per second — **not** "10 at once
> every 100 ms."

> 🟢 **Everyday example.** A theme-park ride that lets one person through the turnstile every few seconds.
>
> Lots of people are *on the ride at once* (that's concurrency), but they're *let in one at a time, paced*
> (that's the send delay).

### Per-minute cap — the minute budget

Separately, each number has a ceiling on how many it will send in a single minute. Today that's **600 per
minute** for WhatsApp Official. Once 600 go out in a minute, it pauses and continues next minute.

> 🟢 **Everyday example.** A parking garage that lets in 600 cars an hour. Doesn't matter how fast cars
>
> arrive — the gate only admits 600.

***

## 3. The golden rule: the slowest dial wins

Here's the part that trips everyone up. The three dials don't add up — **the slowest one decides your real
speed.** Speeding up one dial does nothing if a *different* dial is the bottleneck.

> 🔑 **Real speed = the smallest of these three:**
>
> 1. how fast the **send delay** lets you start sends,
> 2. how many **agents (concurrency)** you have ÷ how long each send takes,
> 3. the **per-minute cap** ÷ 60.

Let's see it with the tap-and-basin picture, then real numbers.

### The tap and the basin

* The **send delay** is a **tap** — how fast water pours in (new sends starting).
* **Concurrency** is the **basin** — how many can sit in it at once (sends in progress).
* Each send sits in the basin \~1.5 seconds, then drains away (WhatsApp replied).

If the tap pours faster than the basin can hold, the basin overflows — so the extra tap speed is wasted.
If the basin is huge but the tap is a trickle, the basin is never full — so the extra basin space is wasted.
**You only go faster when the tap and basin are raised together.**

### Worked examples (WhatsApp Official, each send \~1.5s)

| Send delay       | Concurrency   | What actually happens                                                          | Real speed                               |
| ---------------- | ------------- | ------------------------------------------------------------------------------ | ---------------------------------------- |
| 100 ms (10/s)    | 15 agents     | Tap = 10/s. Basin needs 10 × 1.5s = 15 → exactly full. Balanced.               | **\~10/sec**                             |
| 100 ms (10/s)    | **30 agents** | Tap still 10/s, so still only \~15 in the basin. The extra 15 agents sit idle. | **\~10/sec — no gain**                   |
| **50 ms** (20/s) | 15 agents     | Tap wants 20/s, but 15 agents can only hold 15 in flight → tap blocked.        | **\~10/sec — no gain**                   |
| **50 ms** (20/s) | **30 agents** | Tap 20/s, basin holds 20 × 1.5 = 30. Both match.                               | **\~20/sec ✅**                           |
| 20 ms (50/s)     | 30 agents     | Tap wants 50/s, but only 30 agents → capped by agents = 30 ÷ 1.5.              | **\~20/sec** (tap wasted)                |
| 20 ms (50/s)     | 75 agents     | Tap 50/s, basin 75. Both match.                                                | **\~50/sec** (needs a big database pool) |

**Read the table top to bottom and the lesson jumps out:** raising *only* concurrency (row 2) or *only* the
send delay (row 3) changes nothing. You have to raise them **as a pair** (row 4) to actually speed up.

***

## 4. Why there's a "database pool" limit on the agents

You can't just set 1,000 agents. Every send, when it finishes, has to write a quick note to the database
("this one is done"). The database allows only a certain number of these notes at the same instant — that
shared allowance is called the **connection pool**, and **the whole product shares it** (live chat, incoming
messages, the app screens — not just campaigns).

So if campaigns grab the entire pool, everything else in the product slows down or errors. That's why
concurrency is kept to a safe share of the pool — roughly **60%**, leaving the rest for everyday use.

> 🟢 **Everyday example.** A building with 50 phone lines shared by every department. If the sales team
>
> grabs all 50 for a phone-a-thon, no one else can make a call. So sales is limited to \~30, leaving 20 for
> everybody else.

> **Rule of thumb.** Concurrency should stay around 60% of the database pool. Pool of 50 → keep concurrency
> at about 30. Raising concurrency safely means raising the pool first.

***

## 5. What happens when several campaigns run at once

Everything so far described **one** campaign. But the "agents" (concurrency) are **not** reserved per
campaign or per account — they're **one shared pool for the whole system**. Every campaign that's sending at
the same moment draws from the *same* set of agents.

> 🟢 **Everyday example.** A building has one shared pool of about 15 phone operators. The sales team and
>
> the support team both want to run a phone-a-thon. They don't get 15 each — they **share** the 15. If both
> are busy, each effectively gets about half.

So:

* **The system's *total* speed stays about the same** no matter how many campaigns run — there are still only \~15 agents working at once.
* **But each individual campaign gets a *slice* of that total.** One campaign running alone gets all the agents; three campaigns running together split them.

> 🔑 **One campaign alone = full speed. Many at once = each one slower** — the total is shared, not multiplied.

### Is the split fair?

It's a **fair queue** — first-come, first-served, no campaign jumps ahead. But a campaign's share depends on
**how many "workers" it puts in the queue**, and that isn't the same for every campaign:

> **Workers a campaign uses = (its channels) × (up to 20 per channel — or fewer if it has fewer than 20 messages).**

A campaign with more channels, or fuller channels, has more workers continuously asking for an agent — so it
naturally gets a bigger share. A tiny campaign (only a handful of messages) has very few workers, so it gets
a smaller share. Nobody cuts the line; a big campaign is simply *standing in line many more times*.

### Worked example

Two campaigns sending at the same time, \~15 agents shared:

| Campaign             | Channels × messages     | Workers in the queue | Share of \~15 agents | Speed |
| -------------------- | ----------------------- | -------------------- | -------------------- | ----- |
| **A (big sale)**     | 2 channels, 10,000 each | 2 × 20 = 40          | \~12 agents          | fast  |
| **B (small notice)** | 1 channel, 8 messages   | 8                    | \~3 agents           | slow  |

A has 40 workers in the queue to B's 8, so A asks for an agent far more often and wins \~12 of the 15 — B is
crowded down to \~3. But two campaigns that *each* have at least one full channel (20+ messages) split much
more evenly (\~half each); the lopsided case is when one side is tiny.

### What to do about it

* **For the fastest single campaign, schedule big ones at different times** so they aren't competing for the shared agents.
* **There's no per-account speed guarantee today** — the pool is deliberately one shared ceiling. If a specific account must keep a minimum speed no matter what else is running, that's a separate feature your Lodgestory team can scope.

> 📌 The system also works on up to **10 accounts at a time**. If more than 10 have campaigns due in the
>
> same minute, the extras wait for the next minute — they still send, just slightly later.

***

## 6. "Sent", "Retrying", "Queued", "Failed" — what the dashboard means

On a campaign's page you'll see these counts. Here's each in plain words:

| Word         | What it really means                                                                | Is anything wrong?                              |
| ------------ | ----------------------------------------------------------------------------------- | ----------------------------------------------- |
| **Sent**     | WhatsApp accepted the message for delivery.                                         | No — this is success.                           |
| **Queued**   | Waiting for its **first** attempt. Hasn't been tried yet.                           | No — just hasn't reached the front of the line. |
| **Retrying** | WhatsApp **temporarily refused** it; we'll try again automatically later.           | No — it's working on it. (See below.)           |
| **Failed**   | We tried every retry and it still didn't go (or the number is invalid / opted out). | Yes — this one won't be delivered.              |

> 🔑 **The big one: "Retrying" does not mean stuck.** It means WhatsApp said *"not right now"* — almost always
>
> because of a **marketing-frequency limit** (WhatsApp protects users from getting too many marketing
> messages in a short window). The message will be tried again automatically after a wait. There is nothing
> to fix and **sending faster will not help** — see the next section.

***

## 7. Retries — what "try again later" actually does

When WhatsApp temporarily refuses a message, Lodgestory doesn't give up. It schedules another attempt later.
You control two things:

* **How many times to retry** — 1 to 10 attempts (default 3).
* **How long to wait between attempts** — in hours (default 6, can be 2–72).

> 🟢 **Everyday example.** You call a friend, it's busy. You don't redial instantly 10 times — that won't
>
> help, the line is still busy. You wait a while and try again. WhatsApp's marketing limit is the same: it
> only clears **with time**, so the *wait between attempts* matters far more than the *number of attempts*.

### Why more attempts is usually not the answer

The most common refusal (the marketing-frequency limit) resets on a rolling time window **per recipient**.
Retrying again *before* that window resets just gets refused again and burns an attempt. So:

* **The wait between tries is the powerful dial** (let the window reset — e.g. once a day).
* **More attempts has fast diminishing returns** and, worse, hammering refused recipients can drag your
  number's quality rating down — hurting *all* your campaigns.

> ✅ **Practical recommendation.** For marketing pushes, **3–5 attempts spaced \~24 hours apart** recovers
>
> almost everything that's recoverable. Very high counts (like 10) mostly just keep the campaign showing
> "Retrying" for many days without delivering much more.

### How long will it keep retrying?

Multiply the two dials. 10 attempts × 16 hours apart = up to **\~6.7 days** before it gives up. That's why a
high retry count makes a campaign *linger* — it's not broken, it's patiently waiting between tries.

***

## 8. Putting it all together — three realistic stories

### Story A — "My campaign says Queued and isn't moving"

You scheduled 18,000 messages. Early on, most show **Queued**. That's normal: they're in line, being
released at the paced rate (a few hundred per minute). Watch the **Sent** number climb. Nothing is wrong —
a big list simply takes time at a safe pace.

### Story B — "It says Retrying for thousands and looks frozen"

This is the marketing-frequency limit. WhatsApp accepted some, then refused the rest for now. Those refused
ones are scheduled to retry after your chosen wait (say 16 hours), so the campaign goes quiet, then sends
another wave later. **It will resume on its own.** Sending faster would only produce *more* refusals, not
more deliveries. If anything, run fewer big marketing campaigns to the same audience at once, and prefer a
longer wait between retries.

### Story C — "I want it to genuinely send faster"

First, make sure speed is even your bottleneck (for a throttled marketing list, it isn't — delivery is). If
you have a fresh, non-throttled list and want more raw speed, the dials must move **together**:

1. Raise the **database pool** first (so there's room for more agents).
2. Raise **concurrency** to \~60% of the new pool.
3. Lower the **send delay** to match (so the tap keeps the agents busy).
4. Raise the **per-minute cap** so a minute's budget isn't the new bottleneck.

Example: pool 50 → concurrency 30 + send delay 50 ms + per-minute cap 1,500 → about **20 per second
(\~1,200/min)**, while leaving the rest of the product healthy.

***

## 9. Quick reference

**Today's default speed settings (WhatsApp Official)**

| Setting        | Default           | Means                                |
| -------------- | ----------------- | ------------------------------------ |
| Send delay     | 100 ms            | up to 10 new sends/second            |
| Per-minute cap | 600               | up to 600 messages/minute per number |
| Concurrency    | \~15 (shared cap) | \~15 sends in progress at once       |
| Retry attempts | 3 (max 10)        | tries on temporary refusals          |
| Retry wait     | 6 hours (2–72)    | gap between attempts                 |

**WhatsApp Unofficial** is intentionally much slower (around 6/minute, one at a time) — it's not built for
scale; use Official for big sends.

**The three things to remember**

1. Messages go out as a **paced stream**, not a blast — on purpose, to stay within WhatsApp's limits.
2. **The slowest dial wins** — concurrency, send delay, and the per-minute cap must move *together* to go faster.
3. **"Retrying" is healthy** — it's WhatsApp's marketing limit clearing with time; more speed won't beat it, a longer wait between tries works better.

> Need different speed or retry settings for your account? Your Lodgestory team can tune these per channel —
> share your goal (target send rate, or how long a list should take) and they'll set the dials safely
> against your database pool.

***

*See also: [Campaigns](campaigns.md) for creating and managing campaigns, and
[Bot Journeys](../settings/bot-journeys.md) for handling the replies that come back.*