General
The Asterisk PJSIP DNS SRV Failover Trap: Why Stale Resolver Caches Paralyze Carrier Trunk Redundancy
calricon / field note
When upstream telephony carriers experience node outages, Asterisk PJSIP frequently freezes on failed DNS SRV endpoints instead of failing over. Protracted SIP transaction timeouts drop outbound calls for minutes. Here is the authenticated engineering playbook to eliminate PJSIP DNS SRV failover delays.
The Asterisk PJSIP DNS SRV Failover Trap: Why Stale Resolver Caches Paralyze Carrier Trunk Redundancy
In enterprise telecommunications infrastructures, cloud contact centers, and conversational Voice AI platforms running Asterisk with the modern res_pjsip stack, achieving high availability across carrier SIP trunks is a mandatory architecture goal. Major telecommunications providers—such as Twilio, Bandwidth, Telnyx, and AWS Chime—deliver automated redundancy by publishing DNS Service (SRV) records (RFC 2782) that resolve a single SIP domain to multiple geographical Session Border Controllers (SBCs) weighted by priority. In theory, if Primary SBC 1 experiences an unexpected outage or scheduled maintenance, Asterisk should detect the transport failure instantly and fail over to Secondary SBC 2 with zero call drops. In real-world enterprise operations, however, infrastructure teams encounter an alarming failure mode when a carrier node goes offline: outbound call completion instantly drops to zero percent, live agent and Voice AI dialing queues freeze, and Asterisk holds outgoing calls in limbo for ten to thirty seconds before failing with 503 Service Unavailable or CONGESTION errors. Even worse, Asterisk continues sending new calls to the offline carrier IP for several minutes after the failure occurs, completely ignoring healthy backup nodes. Telemetry dashboards show that host CPU and memory remain normal. The root cause is the Asterisk PJSIP DNS SRV Failover Trap: an architectural state retention failure where aggressive internal DNS resolver caching and default multi-second transaction timers lock PJSIP worker threads to unreachable carrier endpoints, preventing timely dialplan failover.
When an outbound call is placed to a carrier domain using DNS SRV, PJSIP queries the local DNS server and resolves the target SRV record (such as _sip._udp.carrier-domain) into an ordered list of hostnames, port numbers, and priorities. PJSIP selects the highest-priority target (Priority 10) and initiates an outbound SIP INVITE. However, if that remote target is offline or non-responsive, PJSIP does not fail over instantly. Under default Asterisk configurations, the transaction timer (Timer B) enforces a thirty-two-second timeout ceiling (timer_b = 32000). During an outage, Asterisk transmits the initial INVITE and retransmits it seven times across exponential backoffs (Timer T1 starting at 500ms). While this transaction is stuck in retransmission limbo, Asterisk's internal DNS manager caches the resolved IP address in memory. Because standard dialplans execute a single blocking Dial(PJSIP/number@carrier-trunk) instruction without transaction-level exception handling, Asterisk blocks the channel for up to thirty-two seconds. By the time Asterisk declares the transaction failed, the calling customer, Voice AI bot, or transfer agent has already hung up. Furthermore, because PJSIP retains the cached resolved address across subsequent call setups, new outgoing calls are repeatedly dispatched to the exact same non-responsive socket, turning a localized carrier maintenance event into an extended, self-inflicted enterprise outage.
Problem Diagnosis and Root Cause Architecture
Diagnosing PJSIP DNS SRV failover stalls requires tracing how Asterisk's transaction timers, resolver caching, and dialplan execution engines interact during transport outages:
- The Protracted Timer B Serialization Penalty: In RFC 3261, Timer B controls the maximum duration an INVITE transaction will wait for a provisional response (such as
100 Trying). Defaulting to 32 seconds means that an offline carrier SBC paralyzes the channel thread for over half a minute. Under high call concurrency, dozens of worker threads accumulate in timeout states, exhausting threadpools. - Internal Resolver Cache Over-Retention: PJSIP maintains an internal DNS resolution cache that operates independently of the Linux operating system resolver. If
dns_cache_ttlis set to high intervals or left at defaults without active blacklisting, PJSIP refuses to re-query DNS or evaluate secondary SRV weights, repeatedly selecting the failed IP address for subsequent calls. - The Monolithic Dialplan Execution Model: Standard Asterisk dialplans do not implement iterative failover loops. When
Dial()returns a failure status (such asCONGESTIONorCHANUNAVAIL), the dialplan terminates execution unless explicit conditional branching is configured to catch the hangup cause and retry alternate trunk destinations immediately.
A DNS SRV record with five backup SBCs is completely useless if your SIP stack waits thirty-two seconds on the first IP before giving up. In real-time voice infrastructure, failover must occur in under two seconds or your callers will abandon the call.
Why Standard Implementations Fail
Enterprise telephony deployments repeatedly collapse during carrier SBC failovers due to three common configuration oversights:
1. Retaining Default PJSIP Protocol Timers
Administrators routinely deploy pjsip.conf without adjusting base transaction timers. Leaving timer_t1 = 500 and timer_b = 32000 ensures that every failed call attempt consumes half a minute of silence before Asterisk yields control back to the dialplan.
2. Inactive Asterisk DNS Manager Subsystem
Many systems leave Asterisk's internal DNS Manager (dnsmgr.conf) disabled (enable = no). Without the DNS Manager actively refreshing background records at short intervals, Asterisk fails to detect carrier DNS priority updates and IP address rotations.
3. Single-Line Dialplan Execution
Dialplan scripts frequently execute outbound calls with a single unconditional Dial() statement. When an outage trips a carrier error, the call terminates immediately instead of looping to secondary carrier trunks or backup PSTN gateways.
Authenticated Step-by-Step Resolution Playbook
Eliminating DNS SRV failover delays and securing instantaneous carrier redundancy requires tuning PJSIP transaction timers, enabling background DNS management, and implementing rapid dialplan failover loops:
Step 1: Tune PJSIP Transaction Timers and Resolver Caching in pjsip.conf
Update /etc/asterisk/pjsip.conf to compress initial retransmission timers, lower Timer B ceilings, and enforce tight DNS cache expirations:
# /etc/asterisk/pjsip.conf
[system]
type = system
# Compress base retransmission timer to 250ms for rapid failure detection
timer_t1 = 250
# Lower maximum transaction timeout from 32s down to 2.5s
timer_b = 2500
# Global resolver tuning
[global]
type = global
# Restrict internal DNS cache retention to 15 seconds
dns_cache_ttl = 15
# Prohibit serving stale DNS records during carrier outages
dns_cache_stale = no
Compressing timer_b down to 2,500 milliseconds ensures that if an endpoint does not acknowledge an INVITE within 2.5 seconds, Asterisk aborts the transaction immediately and yields control to the dialplan for failover.
Step 2: Enable Active Background DNS Management in dnsmgr.conf
Activate and configure Asterisk's dynamic DNS Manager in /etc/asterisk/dnsmgr.conf to refresh carrier records in the background:
# /etc/asterisk/dnsmgr.conf
[general]
# Enable active background DNS polling
enable = yes
# Refresh carrier records every 30 seconds
refreshinterval = 30
Activating dnsmgr ensures that Asterisk re-evaluates carrier SRV priorities and IP addresses dynamically without requiring manual pjsip reload commands during carrier incidents.
Step 3: Implement an Authenticated Fast-Failover Dialplan Loop
In /etc/asterisk/extensions.conf, replace single-line dial statements with a resilient macro that catches transport congestion and automatically retries across backup carrier trunks within two seconds:
# /etc/asterisk/extensions.conf
[macro-carrier-outbound]
exten => s,1,NoOp(Initiating Resilient Carrier Dialing: ${ARG1})
same => n,Set(DIAL_TIMEOUT=15)
; Attempt primary carrier trunk
same => n,Dial(PJSIP/${ARG1}@primary-carrier-trunk,${DIAL_TIMEOUT},b(set-timer^s^1))
same => n,NoOp(Primary Dial Status: ${DIALSTATUS} | Hangup Cause: ${HANGUPCAUSE})
; Evaluate failure status for immediate failover
same => n,GotoIf($["${DIALSTATUS}" = "ANSWER"]?success:check-failover)
same => n(check-failover),NoOp(Primary Trunk Failed - Executing Instant Failover)
same => n,GotoIf($["${DIALSTATUS}" = "BUSY"]?busy-stop)
; Immediate failover to secondary backup carrier trunk
same => n,Dial(PJSIP/${ARG1}@secondary-carrier-trunk,${DIAL_TIMEOUT})
same => n,Goto(finish)
same => n(busy-stop),Busy(5)
same => n(success),NoOp(Call Successfully Established)
same => n(finish),Hangup()
[set-timer]
exten => s,1,Set(CHANNEL(hangup_handler_push)=carrier-cleanup,s,1)
same => n,Return()
[carrier-cleanup]
exten => s,1,NoOp(Cleaning up channel resources)
same => n,Return()
This dialplan architecture intercepts carrier network drops instantly. If the primary trunk experiences socket silence, Asterisk trips after 2.5 seconds and immediately routes the call out the secondary trunk, bridging the customer seamlessly.
Step 4: Verify DNS SRV Resolution and Failover Timing in Production
Validate that PJSIP resolves SRV records accurately and observe failover behavior using command-line diagnostic tools:
# Verify DNS Manager status and active background lookups
asterisk -rx "dnsmgr status"
# Inspect carrier endpoint status and active contact URIs
asterisk -rx "pjsip show endpoint primary-carrier-trunk"
# Query active PJSIP system timers
asterisk -rx "pjsip show settings" | grep -E "timer_b|timer_t1"
# Monitor real-time failover execution during a live test call
asterisk -rx "core set verbose 3"
Confirm that dnsmgr status reports DNS Manager: Enabled with successful background checks. During failover simulation, verify in the Asterisk console that the transition from primary to secondary carrier completes in under three seconds, proving that stale resolver caching is eliminated.
Enterprise VoIP availability depends on rapid, decisive failure detection at the transport boundary. By compressing PJSIP protocol timers, activating background DNS manager refreshes, and enforcing iterative dialplan failover loops, engineering teams eliminate DNS SRV blackholes and guarantee continuous, uninterrupted telephony operations across global carrier networks.