Skip to content

SMS throttling & pacing

Why phones and carriers limit bulk SMS, how SMSKit paces sends, and how to provision a gateway phone.

Why throttling exists

Two independent systems limit how fast a phone can send SMS, and a gateway phone has to respect both:

  • The Android framework's per-app rate check. Android counts each app's outgoing messages against two system settings — sms_outgoing_check_max_count (how many messages are allowed in the window) and sms_outgoing_check_interval_ms (the window length). The stock default is restrictive — an app that exceeds it gets prompted or blocked by the OS itself. This is anti-spam protection for normal phones, but on a dedicated gateway phone it must be raised so the OS never interferes with server-paced sending.
  • Carrier spam filters. Carriers watch person-to-person numbers for machine-like behaviour. A SIM that suddenly blasts hundreds of messages in a burst can get flagged, filtered, or blocked — sometimes permanently. No setting on the phone changes this; the only defence is pacing your volume like a human would and spreading it across SIMs.

How SMSKit paces sends

Rate limiting in SMSKit is server-authoritative — the pacing decision is made where the queue lives, not on the phone:

  • A per-device hourly limit (default 200 messages/hour) caps how many jobs the server will hand each phone. You change it per device from the dashboard; the phone itself can't edit it.
  • The queue absorbs bursts. Accepted jobs (202) wait in your account's queue and are dispatched as devices have capacity — a burst of API calls doesn't become a burst on the SIM. Within a device's queue, lower priority values are dispatched first.
  • Devices report capacity, the server routes. Each phone reports its remaining hourly capacity on every heartbeat, and the server routes new jobs toward devices with room. The phone applies no throttle of its own — it simply sends what the server hands it.
  • The OS throttle is monitored. The app reads the Android framework's rate-check settings and reports them (with a reliability flag) on registration and every heartbeat, so both the app and the dashboard can warn you when the OS itself might block sends before SMSKit's limit is reached.

What you'll see in the app

On Device Details in the SMSKit Gateway app:

  • Hourly Limit — the server-set per-device ceiling. Read-only on the phone; change it from the dashboard. Note that the Android version and carrier may in practice allow fewer.
  • SMS Throttle — the device's own reading of the Android framework rate check, shown as one of four states:
StateMeaning
Unlimited — OS won’t throttleThe framework check is raised high enough that the OS never interferes. Correctly provisioned.
{max} / {interval}sA real, low OS cap is set — Android may block sends before SMSKit’s own limit. Raise it (see below).
Default (OS)The setting is unset, so the restrictive Android default applies. Raise it for a gateway phone.
Couldn’t verifyThe app couldn’t read the setting on this device/ROM, so it can’t confirm the OS won’t throttle.

Every warning state links to this page. The app never claims "Unlimited" unless it has a reliable, uncapped reading — and it only reads these settings; provisioning them is an operator step, below.

Provisioning a gateway phone (adb)

To stop the Android framework from ever blocking a dedicated gateway phone, raise sms_outgoing_check_max_count to a very large value. This is a one-time step per phone, done over adb with USB debugging enabled:

# Raise the Android framework outgoing-SMS check so the OS never blocks a gateway phone.
# Requires USB debugging (Developer options) and adb on your computer.
adb shell settings put global sms_outgoing_check_max_count 2147483647

# Verify — should print 2147483647:
adb shell settings get global sms_outgoing_check_max_count
  • • The app re-reads and reports the value on every heartbeat, so the Device Details row and the dashboard reflect the change within a heartbeat cycle — no reinstall needed.
  • sms_outgoing_check_interval_ms (the window length) exists too, but with an uncapped max count it doesn't need changing.
  • • Some ROMs block reading these settings — that's the "Couldn't verify" state. The raise usually still works; confirm with the settings get command above.
  • • This only disables the OS interference. SMSKit's per-device hourly limit and your carrier's tolerance still pace actual sending — that's deliberate.

Practical guidance for volume

  • Keep the hourly limit conservative. The default 200/hr exists to keep carriers happy and your SIM un-flagged. Raise it gradually and watch deliverability rather than jumping to the maximum.
  • Scale with SIMs and phones, not with speed. Throughput in SMSKit is additive: two phones at 200/hr are 400/hr. A dual-SIM phone spreads volume across two carrier identities. Adding a device is safer than pushing one SIM harder.
  • Spread bulk over time. Queue big batches and let the per-device limit pace them out instead of expecting instant delivery — and give urgent messages a lower priority value so they jump ahead of the batch.
  • Watch the throttle row. If Device Details or the dashboard shows a throttle warning, fix it before a campaign — an OS block mid-batch looks like random send failures.

Related: API rate limits & errors · priority on send · device setup.