How-to

Outbound rate limiting

Sliding-window rate limit per destination phone number using a Redis sorted set. Alert-only by default; flip to blocking when confident.

Before every outbound call Breeze Buddy checks how many times it has dialed the same destination in a rolling window. If the count exceeds the limit it either sends a Slack alert or blocks the call, depending on config. The limiter is Redis-backed and atomic — no race conditions under concurrent load.

Prerequisites

  • Redis reachable from the application (REDIS_HOST, REDIS_PORT).
  • Optional: Slack webhook for alerts (SLACK_WEBHOOK_URL).
  • Outbound calling enabled — see Call execution configuration.

How it works

For each destination phone number, Breeze Buddy maintains a Redis sorted set with {timestamp}:{lead_id} members scored by timestamp. An atomic Lua script runs before each call:

  1. Trims entries older than now - window_seconds.
  2. Counts remaining calls.
  3. Records the current call.
  4. Returns the pre-insert count.

If count >= max_calls, the limit is tripped.

Key settings

Env varDefaultControls
OUTBOUND_RATE_LIMIT_MAX_CALLS7Maximum calls per destination in the window.
OUTBOUND_RATE_LIMIT_WINDOW_SECONDS3600Rolling window length in seconds.
OUTBOUND_RATE_LIMIT_BLOCK_ENABLEDfalsetrue blocks the call. false sends an alert and lets the call proceed.

Example config

.env
bash
OUTBOUND_RATE_LIMIT_MAX_CALLS=7
OUTBOUND_RATE_LIMIT_WINDOW_SECONDS=3600
OUTBOUND_RATE_LIMIT_BLOCK_ENABLED=false
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx

Start in alert-only mode. Watch the Slack channel for a week or two to confirm the limit isn’t too aggressive, then flip OUTBOUND_RATE_LIMIT_BLOCK_ENABLED=true.

Operational notes

  • Atomicity — the Lua script guarantees atomicity. Even under high concurrency on the same destination, every call sees a consistent count.
  • Redis unavailable — the check is skipped fail-open. The call proceeds and is logged for audit. Redis outage will not halt outbound calling.
  • TTL self-cleanup — keys auto-extend their TTL on activity and auto-delete when a number stops being called. No manual cleanup.
  • Blocked calls — when blocking is enabled, the lead is released back to the queue; you can retry or cancel via the Leads API.
  • Noisy numbers — the limit is per destination, not per merchant. If your workload legitimately calls the same number repeatedly (e.g., warm-up tests), exclude those numbers in a separate channel.

Separate from telephony-provider rate limits

This limit is enforced by Breeze Buddy before the provider is called. Provider-side rate limits (Twilio account-level, Plivo app-level) are independent and may still fire.

Next steps

Was this helpful?