Channels and preferences Required
Cap how many messages one person gets
Set a maximum number of push and text messages per person per day, and per type per hour. Fold the overflow into a digest or the inbox.
How to do it
Count sends per user and channel in a sliding window, for example in Redis or a sends table with an index on user and time. Start with caps such as 5 pushes and 2 marketing texts a day. Critical types do not count against the cap, but get their own cap to stop a loop, such as 20 a day. Alert when many users hit the cap at once, because that usually means a bug.
Example
-- Must return 0 rows
SELECT user_id, channel, count(*) FROM sends
WHERE sent_at >= now() - interval '1 day' AND urgency <> 'critical'
GROUP BY user_id, channel
HAVING count(*) > CASE channel WHEN 'push' THEN 5 WHEN 'sms' THEN 2 ELSE 1000 END;
const DAILY_CAP = { push: 5, sms: 2 };
export const underCap = async (userId, channel) =>
(await db.sends.countSince(userId, channel, Date.now() - 86_400_000)) < (DAILY_CAP[channel] ?? Infinity);
from datetime import UTC, datetime, timedelta
DAILY_CAP = {"push": 5, "sms": 2}
def under_cap(user_id, channel):
since = datetime.now(UTC) - timedelta(days=1)
return db.sends.count_since(user_id, channel, since) < DAILY_CAP.get(channel, float("inf"))
How to check
A test sends 50 events of one type to one user in a minute. At most the cap goes out, and the rest land in the inbox. The sends table shows no user above the cap yesterday.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers notifications playbook: https://agentwranglers.se/playbook/notifications/channels-and-preferences/notification-rate-caps.