# SMPP enquire_link, windowing and throttling

> enquire_link (0x00000015) is a lightweight keepalive that confirms a bound SMPP session is still healthy over TCP. Throughput is governed by two limits: the window (how many PDUs may be un-acknowledged at once) and the provider's TPS ceiling. Exceeding the rate returns ESME_RTHROTTLED (0x00000058); the fix is to back off.

- Canonical URL: https://www.broadnet.me/reference/smpp-enquire-link-throttling
- Language: en
- Last updated: 2026-07-18
- Publisher: BroadNet (https://www.broadnet.me)

How SMPP keeps a session alive with enquire_link, how the window limits outstanding un-acked PDUs, and how ESME_RTHROTTLED and per-bind TPS govern your real throughput.

## enquire_link keepalive

A bound SMPP session can sit idle for long periods, and a half-open TCP connection looks alive at the socket level. enquire_link solves this: either peer sends it on an idle timer (commonly every 30–60 seconds) and expects an enquire_link_resp promptly. A missed response means the session is dead — tear down the TCP connection and reconnect with backoff. It is the only reliable way to detect a silently broken link.

*Keepalive exchange*

```text
ESME → SMSC  enquire_link      seq=1200
SMSC → ESME  enquire_link_resp seq=1200  status=ESME_ROK
  (no response within timeout ⇒ treat session as dead, reconnect)
```

## The window: outstanding un-acked PDUs

SMPP is asynchronous: you can send many submit_sm PDUs before their submit_sm_resp arrives. The window size caps how many may be outstanding (un-acknowledged) at once. When the window is full you must pause submitting until a response frees a slot. Firing past the window is a leading cause of throttling and dropped PDUs. Window size is agreed with the provider — there is no single protocol default.

## Throttling and TPS

Separately from the window, the provider enforces a maximum message rate — transactions per second (TPS) — per bind or per account. Exceeding it returns ESME_RTHROTTLED (0x00000058). The correct response is to slow down: pause, back off with jitter, and resume below the ceiling. Never retry a throttled PDU immediately or open extra binds to get around the limit — both risk the account being suspended. On v5.0 the SMSC can additionally advertise congestion via the congestion_state TLV so ESMEs can pre-emptively slow down.

*The three limits that shape throughput*

| Limit | Governs | Breach signal |
|---|---|---|
| Window size | Un-acked PDUs in flight | Backpressure / dropped PDUs |
| TPS ceiling | Messages per second | ESME_RTHROTTLED (0x58) |
| Bind count | Parallel sessions | Bind refused / account action |

## Tuning for sustained throughput

Real throughput is roughly the window size divided by the round-trip latency, capped by the TPS ceiling. A larger window helps on high-latency links; more binds help only if the provider provisions them. Instrument window occupancy, submit/response latency and throttle-error rate, and treat a rising ESME_RTHROTTLED rate as the signal to reduce send rate rather than push harder.

## Frequently asked questions

### How often should I send enquire_link?

Commonly every 30–60 seconds on an idle timer. Send it when the session has been quiet, and treat a missing enquire_link_resp within your timeout as a dead session that must be reconnected.

### What is the SMPP window size?

The window is the maximum number of PDUs you may have outstanding (sent but not yet acknowledged) at once. It is negotiated with your provider rather than fixed by the protocol; pause submitting when the window is full.

### How do I fix ESME_RTHROTTLED?

Reduce your send rate. Pause, back off with jitter, and resume below the provider's TPS ceiling. Do not retry immediately or open additional binds to bypass the limit — both can get the account throttled harder or suspended.

### Does a bigger window increase my TPS?

Up to a point. Throughput is roughly window size divided by round-trip time, but it is still capped by the provider's TPS ceiling. A larger window mainly helps hide latency on high-RTT links.

### What is congestion_state in SMPP v5.0?

v5.0 adds a congestion_state TLV that lets the SMSC advertise how loaded it is (0–100). A cooperative ESME reads it and pre-emptively slows down before hitting hard throttling, smoothing throughput under load.

## Sources

- [SMPP v3.4 specification — §4.11 enquire_link](https://smpp.org/SMPP_v3_4_Issue1_2.pdf)
- [SMPP v5.0 specification — congestion state](https://smpp.org/SMPP_v5.pdf)

## Related

- [SMPP command_status error codes](https://www.broadnet.me/reference/smpp-command-status-errors)
- [SMPP bind operations](https://www.broadnet.me/reference/smpp-bind-operations)
- [SMPP integration best practices](https://www.broadnet.me/reference/smpp-integration-best-practices)
- [SMPP error-code lookup (free tool)](https://www.broadnet.me/tools/smpp-error-codes)
- [SMPP integration checklist (guide)](https://www.broadnet.me/guides/smpp-integration-checklist)
