Skip to main content

Peak-season capacity rehearsal

A flash sale exercises six controls at once: your per-key rate limits, campaign send pacing, spend caps, anomaly alerts, fallback chains, and carrier throughput ceilings. Each has its own guide; this page rehearses them together, in order, before the spike arrives, so the event runs on settings you tested instead of settings you discovered. Work the sections in order against one real campaign. Every control below is tenant-owned: you set it, test it, and clear it yourself.

1. Estimate the spike against your per-key rate limits

Start with a number: peak sends per minute, not total volume. A 300,000-message blast compressed into a 20-minute flash-sale window is 15,000 sends/min; the same volume over six hours is 833. Compare the peak against the rate limits your key carries: The arithmetic decides your path. 15,000 SMS/min at 100/min per key is 150 keys’ worth of default quota: that is an override request, not a key-splitting exercise. 800/min is eight keys or one override, and may simply be a scheduling problem your campaign’s send window already solves.
  • Within quota with headroom. Proceed; keep the bounded retry pattern from the rate-limits guide so a brief 429 never drops sends.
  • Over quota. Email support@devotel.io with the endpoints you need raised and the sustained rate you expect, the same path the go-live checklist prescribes. Request the per-organization override before launch day: an override reviewed and in place a week early is configuration; one requested mid-event is an incident.
Forecast the peak from the same number every section below uses. If the estimate changes later, re-run this section; everything downstream derives from it.

2. Enable adaptive pacing per campaign

Adaptive pacing is the closed-loop rate controller that reads each campaign’s own delivery receipts per carrier and slows the blast when a carrier starts failing or spam-blocking. It is off by default and opt-in per campaign:
Set it on every blast-type campaign in the event (via the campaign composer or PUT /api/v1/campaigns/:id), and know what it will do to the send curve before it happens:
  • Healthy traffic changes nothing. The pace factor stays at 1 and the campaign runs at its configured throttle_rate, flat.
  • A stressed carrier bends the curve instead of breaking it. As a carrier’s failure-plus-block rate climbs from 5% toward 30%, the effective send rate scales down proportionally (a 50 MPS campaign under factor 0.6 sends 30 MPS and the inter-batch gap widens to match). The blast stretches in time rather than hammering a blocked destination for hours.
  • It slows; it never halts. The floor factor is 0.2, so even a fully throttled carrier keeps draining at 20% of rate. A hard stop is not pacing’s job. That is section 3.
On flash sales this matters most in the first hour, when a destination network that has never seen your volume can start filtering it. Pacing turns that into a visible slowdown you can read in the campaign’s per-carrier delivery breakdown, instead of a flat wall of rejected traffic you discover in the morning. Skip it on triggered drip and journey sends: there is no batch volume to pace and no per-window receipt signal.

3. Set spend caps to pause, and drill the over-cap path in sandbox

A runaway blast during an event should stop at the budget you chose, not at the balance you discover afterwards. In Billing → Alerts, set the monthly budget first (percent rules are inert without it), then a two-layer ladder:
  • 70% of budget, action_on_hit: "notify" — hours of warning, traffic untouched.
  • 90% of budget, action_on_hit: "pause_outbound" — the hard stop. New sends return 402 SENDING_PAUSED, refused pre-dispatch, never charged, never sent to the carrier.
Choose pause_outbound, not block_outbound, for the event stop. A tripped pause re-arms with one clear action in Billing → Alerts after you raise the threshold; a block holds for operator review, which is the right posture for fraud, not for a budget line you expect to raise mid-event when the sale works. The full rule reference and recovery levers live in Spend caps on the dashboard. Then rehearse the over-cap path against a sandbox key (dv_test_sk_*) so the first time the gate fires is not the first time anyone sees it:
  1. Set a small sandbox monthly budget (for example $5).
  2. Create a spend_amount rule with a threshold of one message’s cost and action_on_hit: "pause_outbound".
  3. Send one sandbox SMS to a magic number such as +15005550002.
  4. Wait for the billing scheduler’s 10-minute tick; confirm the notification lands and the wallet header shows the org paused; confirm a further send returns 402 SENDING_PAUSED.
  5. Clear the alert in Billing → Alerts and confirm the next send goes through.
The rule shape is identical in live mode; only the key differs. If a tripped cap should not be the only funding risk, pair it with auto top-up so a healthy event does not stall on an empty wallet.

4. Wire anomaly alerts to the on-call channel

Spend caps enforce; usage anomaly alert rules tell you where to look. Create org-scoped rules over the three metrics that move during an event: Create them at POST /api/v1/usage/alert-rules or in the console under Insights → Usage alert rules. Know where the alerts land before you rely on them: rules fire into the dashboard Notification Center (notify_channels accepts in_app only today). To page an on-call channel, poll GET /api/v1/usage/alert-rules/events from your own bridge; the fired-event feed is the integration surface, capped at the last 50 events, newest first, with the breach sentence and a deep link in every entry. A small poller against that endpoint is the supported way to put these alerts in your on-call rotation; respect cooldown_hours so a sustained breach re-pages at most once per cooldown. Test each rule with Evaluate now (POST /api/v1/usage/alert-rules/evaluate) or the console button, and confirm the fired entry appears in the feed before the event.

5. Preflight every fallback chain

A waterfall leg that dies mid-event is worse than no fallback: the primary fails at peak and the chain hands your traffic to a channel you never verified. For every campaign carrying order >= 1 legs, run the read-only dry-run preview:
Read channel_waterfall per step: channel_connected: true means the leg can send from a tenant-connected sender; false means the leg ships nothing you verified (buy the number, connect the sender, then re-run); null means the channel cannot be probed and makes no claim either way. ready_to_launch returns true only with an empty warnings list and a passing provider aggregate, so a flagged leg suppresses the green banner instead of hiding behind it. The per-warning meanings and the dashboard panel are in Pre-launch readiness for fallback chains; the channels[] ladder itself is in the fallback chains guide. Re-run the preview after any sender or number change between rehearsal and launch, not just once.

6. US A2P throughput: 10DLC tier math and message-class mix

For US SMS the carrier-granted ceiling, not your platform quota, is the outer bound. Resolve your brand’s numbers with the 10DLC throughput and cost calculator: slide in your TCR trust-vetting score and read the two ceilings that matter: Two multipliers people miss on launch day:
  • Segments count as parts. A 160-character SMS is one part; a 400-character one is three. T-Mobile’s daily cap is in parts, so long promotional copy spends the cap three times as fast.
  • The use-case code moves your lane. A MIXED registration lands on a reduced daily-cap lane; where a single use case fits, register it explicitly (a dedicated MARKETING campaign gets its own classification). The message-class mix of your event traffic belongs in this calculation, not in a footnote.
Compare the granted ceilings against the section-1 forecast in parts per minute and parts per day. Carriers throttle or filter above the cap without a hard error, so enforce the ceiling where sends run: set per-campaign throughput ceilings beneath the carrier grant per campaign limits and quiet hours. If the grant is below the forecast, that is a registration problem (re-vet, additional campaigns) to solve weeks early, per the 10DLC registration guide, not a pacing tweak on launch day.

7. Launch-day runbook

T-1 h. Re-run the fallback preview on every event campaign; confirm each anomaly rule shows OK or Not yet evaluated and is enabled; confirm the wallet is funded past the 90% pause threshold you expect the event to need; confirm the rate-limit override (if requested) is in effect by reading X-RateLimit-Limit on a live-key request. During the event, three surfaces show the truth live:
  • Insights — the delivery KPI cards and the usage alert rules table (last_status / last_value per rule), the same numbers the alert rules evaluate, so a breach and the dashboard agree.
  • Notification Center — fired usage alerts and spend-cap notifications, severity warning, with deep links.
  • Billing → Alerts — month-to-date spend against the ladder, and the org paused state in the wallet header if the 90% rule trips.
Abort surfaces, mildest to hardest:
  1. Pause the campaign — stops one blast, everything else keeps sending.
  2. Let the spend cap pause the org (402 SENDING_PAUSED) or clear it deliberately — stops all outbound until a human clears the alert; this is the budget stop you drilled in section 3.
  3. Compliance emergency stop — the organization-level halt for the regulatory or content emergency, covered in Compliance emergency stop. Know where it is before you need it; it is not a budget tool.
Post-event, read the delivery funnel (sent → delivered → failed per channel and carrier) in Insights before you judge the event’s deliverability, and pull the cost split from the billing records export to reconcile what the blast actually cost against the what-if preview you ran in rehearsal. Feed both into the next forecast: the section-1 number you got wrong is the one to fix first.

The rehearsal in one list

  • Peak sends/min forecast written down; per-key limits compared; override requested early if over quota.
  • adaptive_pacing enabled on every blast campaign.
  • Monthly budget set; 70% notify and 90% pause_outbound rules live; sandbox over-cap drill passed end to end.
  • Anomaly rules for delivery rate, volume, and spend created, evaluated, and bridged to on-call via the events feed.
  • Fallback preview re-run on every chained campaign; no channel_connected: false leg.
  • 10DLC ceilings resolved in parts (score, segments, use-case mix) and per-campaign throughput set beneath them.
  • Runbook owners named for pause, cap-clear, and emergency stop.