Fundamentals
SIP Session Timers: The Heartbeat of a Long Call
SIP has a memory problem: once a call is established, nothing in the base protocol proves both sides are still there. If a phone loses power mid-call, the other side could talk into the void indefinitely and trunks would leak capacity. Session timers (RFC 4028) are the fix: the call negotiates an expiry, one side is assigned to refresh it with periodic re-INVITEs or UPDATEs, and if the refresh stops, the call is torn down cleanly.
They are also — as the timed-drops guide documents — a leading suspect when calls die at suspiciously exact durations. This is the mechanism underneath that symptom.
The negotiation, piece by piece
| Element | Meaning |
|---|---|
| Session-Expires (seconds) | The maximum time between refreshes before the session is considered dead; commonly 1800 (30 min); RFC floor is 90s |
| refresher=uac / uas | Which side must send the refresh — negotiated in the INVITE/200 OK exchange via the 'Supported: timer' machinery |
| Min-SE | The smallest Session-Expires a side will accept; low offers get a 422 response carrying the minimum, and the caller retries higher |
| Refresh at half-interval | By convention the refresher acts at half the expiry, leaving a full interval to recover from a lost refresh — the origin of the 'dies at 15 on a 30-minute timer' pattern |
| Refresh vehicle | A re-INVITE or an UPDATE inside the dialog; either must traverse the same path and survive the same intermediaries as the original INVITE |
How alignment fails in production
Session timers fail socially, not mathematically: the two ends and every intermediary must all cooperate. Failure modes repeat across networks: a NAT/firewall lets the signaling association idle so the refresh re-INVITE dies in transit (while media, busier, keeps its own path warm — the call sounds perfect until it vanishes); an SBC enforces a shorter expiry than the PBX negotiated and tears down 'early' by the PBX's reckoning; one side doesn't support the timer extension and the other requires it (Require: timer), ending calls at setup or first refresh; and a proxy that record-routed the original dialog is bypassed or reboots, so the refresh takes a path where nobody knows the dialog. The diagnostic constant: find the Session-Expires negotiation in the setup, compute the expected refresh moment, and read the capture at that moment — the refresh's fate is written there.
Align timers across a path
- Inventory the positions: PBX/platform session-timer settings (expiry, whether required, refresher preference) and the provider/SBC's documented values — mismatches hide in defaults.
- Choose one expiry for the path (1800s is a sane default) and ensure no element enforces a shorter one silently.
- Keep the signaling path warm: NAT/firewall UDP timeouts for SIP above the refresh interval's needs, keepalives enabled — a refresh must never meet a closed pinhole.
- Decide support posture consistently: if a peer cannot do session timers, negotiate their absence cleanly rather than letting one side assume a heartbeat that never comes.
- Test with a call held past two refresh points while capturing; the refresh exchange should be as boring as the setup was.
Frequently asked questions
- Why refresh at half the expiry instead of near it?
- Insurance: if the refresh at T/2 is lost, there is still T/2 remaining to retry before the session is declared dead. It converts a single lost packet from a dropped call into a non-event.
- Can session timers be turned off entirely?
- If both ends agree (the extension is optional unless required), calls run without refresh — at the cost of zombie sessions when an endpoint vanishes silently. Most operators keep timers and align them; disabling is a diagnostic step, not a destination.
- Our long calls die but the capture shows the refresh succeeding.
- Then look one layer down: an intermediary with its own shorter media or session policy (an SBC media-inactivity timer is the usual second suspect), especially on calls that sit muted — media silence and refresh success coexist there.