One Parameter, Nine Hundred Characters
Two of the six chat connectors send one message to one place. The other two send the same message to a list, one request each — which means they can half-succeed, and a result that is only true or false throws away the half you needed to know about.
There is a question that only appears once a notification has more than one destination, and it has no comfortable answer. Four of six recipients got the message. Did the send succeed? Yes is wrong. No is also wrong, and worse, because it will make somebody go looking for a failure that affected two people out of six while the other four already acted on it.
Two shapes of chat connector
The six chat destinations split cleanly in two, and the split is not about the vendor — it is about what a destination is.
| Shape | Who | One send is | What comes back |
|---|---|---|---|
| A place | Slack, Teams, Discord, Google Chat | One request to one webhook | Accepted, or a reason |
| A list of people | WhatsApp, Telegram | One request per recipient | How many landed, how many did not, and why |
A channel is a single destination, and everybody in it sees one message. There is nothing to count. A list of phone numbers or chat identifiers is genuinely several sends, and each can fail on its own for reasons that have nothing to do with the others — this number is not registered, that person blocked the bot, this identifier was a group somebody left.
A boolean is the right return type for one destination and a lossy one for a list.
So the fan-out connectors count
Both of them return three things rather than one: how many were sent, how many failed, and the reason the last failure gave.
The overall verdict is deliberately strict. It is not did anything get through — it is everything got through and nothing did not. Four of six is a failure, reported as a failure, with the count that says it was four of six.
That strictness is the right way round for an operational alert. A partial delivery on an approval request means someone who needed to know does not, and a green tick over that is a false statement about who has been told. The count is what stops the strict verdict from being useless, because it turns failed into failed for two of them, and here is what the provider said.
One consequence is worth naming plainly: an empty recipient list is reported as a failure rather than a success. Nothing failed, but nothing was sent either, and the alternative — a connector that is configured, enabled, and cheerfully reports success while reaching nobody — is precisely the silent state these posts keep coming back to.
Why the last error rather than the first
A small choice with a practical reason behind it. When several recipients fail, the reason kept is the most recent one.
The realistic failure pattern is not a random scatter — it is a shared cause. An expired token, a suspended number, a rate limit. When the cause is shared, every failure carries the same message and it does not matter which one is kept.
When the cause is not shared, the count is what tells you so: one failure out of eight is an individual problem with one recipient, and eight out of eight is a problem with the connector. The count carries the diagnosis and the message carries the detail, which is why keeping one message rather than a list of eight identical ones loses nothing worth having.
Nine hundred characters, and what falls off the end
On WhatsApp there is a second constraint, because the notification has to fit through a single template slot.
The title and the detail are joined into one string and capped, with an ellipsis marking where the cut happened. That cap is generous — most operational notifications are a fraction of it — but it is a real ceiling and it has a consequence worth designing around.
The title comes first. So a notification that runs long loses the end of its detail and keeps the sentence that says what happened. That ordering is the whole mitigation: the part that survives truncation is the part that has to survive, and it survives because of where it sits rather than because anything measures it.
It is the same principle as the plain-text line Slack needs for phone notifications. Design the message so that the first line alone is worth receiving, and every downstream constraint — a lock screen, a template slot, a character cap — stops being a problem and becomes a trim.
One more detail, invisible and load-bearing
The message body for each recipient is built fresh inside the loop rather than constructed once and reused.
On the face of it that is wasteful — the content is identical for everybody. What it buys is that no recipient can be affected by what happened to the one before. A payload assembled once and then modified per send is the classic way one recipient's address ends up on another recipient's message, and the bug does not show up until the list has more than one entry on it.
Rebuilding is a handful of array allocations against a network call that costs a thousand times more. It is one of the cheapest correctness guarantees available and it is invisible in every test with a single recipient — which is every test anybody writes first.
What is in place, layer by layer
Fan-out delivery, end to end
One request per recipient
Each destination gets its own send, so one bad number cannot take the rest of the list with it.
Counted results, not a boolean
How many landed and how many did not, so a partial delivery reads as a partial delivery rather than as either a success or a total failure.
A strict overall verdict
Anything less than all of them is reported as a failure, because a partial delivery on an approval means somebody who needed to know does not.
An empty list reads as a failure
A configured connector with nobody to send to is not reported as a success, because reaching nobody quietly is the exact state worth surfacing.
The provider's reason carried back
The failure message is the provider's own — an unregistered number, a blocked bot, a rate limit — read from where they put it rather than paraphrased.
A per-recipient payload
The message is rebuilt for each send rather than assembled once and adjusted, so nothing from one recipient can survive into the next.
Truncation that keeps the headline
Where a template slot caps the length, the title leads and the detail is what gets trimmed, with an ellipsis marking the cut.
A ceiling per send
Each recipient's request is individually bounded, so a slow response part-way down a list does not stall the rest of it.
The four channel-based connectors return a single accepted-or-refused result instead, because there is one destination and nothing to count. The shape of the return follows the shape of the destination.
Three positions held on purpose
- A partial delivery is a failure with a number attached, not a success. Reporting four of six as fine is a statement about who has been told, and it is a false one.
- Sending nobody a message is never reported as success. An empty recipient list on a live connector is a real condition someone should see, and the only way they see it is if it is not quietly counted as fine.
- Each send is built independently. The saving from assembling one payload and reusing it is negligible, and the failure it enables — one recipient's details on another's message — is invisible in every single-recipient test.
Five questions about a notification that goes to several people
What if some recipients fail?
A good answer sounds like
Counted and reported.
What ours actually is
How many landed, how many did not, and the provider's reason for the failure.
Is four out of six a success?
A good answer sounds like
No.
What ours actually is
The verdict requires all of them. The count is what makes that verdict actionable rather than alarming.
What if the recipient list is empty?
A good answer sounds like
That is a failure.
What ours actually is
Reported as one, because a live connector reaching nobody is a condition worth seeing.
Can one recipient's data leak into another's message?
A good answer sounds like
Structurally, no.
What ours actually is
The payload is rebuilt per send rather than assembled once and modified.
What happens to a very long notification?
A good answer sounds like
The headline survives.
What ours actually is
The title leads and the detail is trimmed with an ellipsis, so the part that matters is the part that fits.
Our take
Return types are where a system quietly decides what it is able to tell you. A function that answers true or false has already thrown away the fact that two of six recipients did not get the message, and no amount of care further up can recover it — the information is gone at the point it was compressed. This is the most portable lesson in the whole connector series: when you find yourself writing a boolean for something that happened several times, the boolean is wrong, and every diagnostic problem you have with that feature for the next two years starts there.
Know who actually got told
On a channel it is everyone or nobody. On a list it is a number, and a notification system that cannot tell you the number cannot tell you whether the alert worked.
Talk through operational alertsFrequently asked questions
If two recipients fail, do the other four still get the message?
Yes. Each recipient is a separate send, so a failure on one has no effect on the rest of the list. What the result reports is that four landed and two did not, with the reason the provider gave.
Why is the whole send marked as failed when most of it worked?
Because the alternative is a green tick over a message somebody never received. The strict verdict plus the count is more useful than a lenient verdict: you learn immediately that not everyone was told, and the number tells you whether it is one bad number or a broken connector.
Will a failed recipient be retried?
Where the notification runs as background work, the usual retry rules apply to the send as a whole. Because these are notifications rather than records, the design bias is toward reporting clearly rather than retrying aggressively — a duplicate alert costs a glance, and the record in your workspace is the authority either way.
How long can a notification be before it is trimmed?
The WhatsApp template slot is capped at a length most operational alerts sit well inside. If a message does run long, the title survives and the detail is trimmed with an ellipsis, so the notification still says what happened.
Can different recipients get different messages?
No — a notification is one message sent to the list. Routing different events to different audiences is done by which destination an event type is sent to, rather than by varying the content per person, which keeps the message the same fact for everybody who receives it.