← All Tutorials

Asterisk Queue Strategy Guide — Which Ring Strategy to Use

Infrastructure & DevOps Intermediate 16 min read #52

Master ring strategies to optimize call routing, reduce agent idle time, and improve contact center performance in ViciDial and Asterisk environments

Introduction

Ring strategy determines how Asterisk distributes calls across available agents in a queue. Choose the wrong strategy and you'll watch call times spike, agents go idle despite having calls waiting, and customers hear excessive hold times. Choose correctly and you maximize agent utilization while maintaining quality.

This guide walks you through every ring strategy Asterisk supports, explains when to use each one, and shows you exactly how to configure and monitor them in production ViciDial environments. You'll learn which strategies work best for predictive dialing, inbound call centers, and hybrid operations—and how to troubleshoot when ring strategy causes problems.

Prerequisites

Before implementing ring strategies in your Asterisk/ViciDial environment, confirm you have:

If you're unfamiliar with ViciDial queue setup, run asterisk -rx "queue show" to verify your existing configuration is loading.

Understanding Asterisk Ring Strategies

Ring strategy is set in the queue.conf file and controls member selection when a call arrives in queue. Asterisk evaluates the strategy, picks the next agent, and sends the call to that extension.

Ring Strategy Types

Asterisk supports six core strategies:

  1. linear — Cycles through members in order (first-in-queue order)
  2. round-robin — Distributes calls evenly, tracking position
  3. round-robin queue member — Tracks per-queue position (most common in ViciDial)
  4. random — Selects random available agent
  5. fewest-calls — Routes to agent with fewest calls handled
  6. longest-idle — Routes to agent idle longest (agent reuse prevention)

ViciDial defaults to round-robin queue member for good reason: it balances load without requiring call counts and prevents agent burnout from rapid consecutive calls.

Why Ring Strategy Matters in ViciDial

In predictive dialers, agents answer calls immediately—ring strategy doesn't impact speed much. But in inbound queues and blended operations, ring strategy determines:

Linear Ring Strategy

Linear sends each new call to the next agent in the queue member list, cycling from top to bottom. Once it reaches the last member, it restarts at the top.

When to Use Linear

When NOT to Use Linear

Linear Configuration

[general]
persistmembers = yes

[inbound_queue]
type = queue
strategy = linear
members = SIP/2001,SIP/2002,SIP/2003
timeout = 15
retry = 5
maxlen = 0
announce-frequency = 60
announce-holdtime = yes

Testing Linear in ViciDial

Verify the queue is loaded and check member order:

asterisk -rx "queue show inbound_queue"

Expected output:

Queue: inbound_queue
  Members: 
    SIP/2001 (dynamic) (In Call)
    SIP/2002 (dynamic) (Not in use) (Penalty: 0)
    SIP/2003 (dynamic) (Not in use) (Penalty: 0)
  Strategy: linear
  Calls in queue: 2

The next call goes to SIP/2002 (first available after SIP/2001).

Linear in ViciDial Database

Check queue configuration in the vicidial database:

SELECT * FROM vicidial_queues WHERE queue_name = 'inbound_queue'\G

If you don't see a queue_strategy field, your ViciDial version stores strategy only in extensions-vicidial.conf.

Round-Robin Ring Strategy

Round-robin selects agents in order, but remembers position between calls. Call 1 goes to agent 2, call 2 goes to agent 3, call 3 goes to agent 1—cycling continuously.

When to Use Round-Robin

When NOT to Use Round-Robin

Round-Robin Configuration

[general]
persistmembers = yes
autofill = yes
autofillweight = 0

[sales_queue]
type = queue
strategy = round-robin
members = SIP/3001,SIP/3002,SIP/3003,SIP/3004
timeout = 20
retry = 5
maxlen = 0
announce-frequency = 60
announce-holdtime = yes
joinempty = yes
leavewhenempty = yes

Round-Robin in ViciDial

Create a test queue and monitor call distribution:

# Reload config
asterisk -rx "core reload"

# Check position tracking
asterisk -rx "queue show sales_queue"

# Make test calls and observe position change

After 4 calls, you'll see position reset to the beginning.

Round-Robin Queue Member Strategy (RRQM)

This is ViciDial's default and recommended strategy. It's identical to round-robin but resets position per queue, not globally. This is critical when agents belong to multiple queues.

Why RRQM for ViciDial

In a production contact center:

When to Use Round-Robin Queue Member

RRQM Configuration

[general]
persistmembers = yes
autofill = yes
autofillweight = 0

[inbound_sales]
type = queue
strategy = rrmemory
members = SIP/4001,SIP/4002,SIP/4003,SIP/4004,SIP/4005
timeout = 25
retry = 5
maxlen = 0
announce-frequency = 60
announce-holdtime = yes
joinempty = yes
leavewhenempty = yes
weight = 100

[inbound_support]
type = queue
strategy = rrmemory
members = SIP/4001,SIP/4002,SIP/4006,SIP/4007
timeout = 30
retry = 5
maxlen = 0
announce-frequency = 60
announce-holdtime = yes
joinempty = yes
leavewhenempty = yes
weight = 80

Here, SIP/4001 and SIP/4002 are in both queues. RRQM maintains separate position tracking for each queue.

Verifying RRQM in Production

Check the active strategy:

asterisk -rx "queue show inbound_sales" | grep Strategy

Output:

Strategy: round robin with memory

Check agent distribution over 1 hour:

SELECT 
  user_extension,
  COUNT(*) as call_count,
  AVG(call_duration) as avg_duration
FROM vicidial_closer_log
WHERE call_date >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
  AND queue_name = 'inbound_sales'
GROUP BY user_extension
ORDER BY call_count DESC;

Equal call counts across agents confirms RRQM is working.

Random Ring Strategy

Random selects any available agent at random. No position tracking, no fairness guarantee per-call.

When to Use Random

When NOT to Use Random

Random Configuration

[testing_queue]
type = queue
strategy = random
members = SIP/5001,SIP/5002,SIP/5003
timeout = 15
retry = 5
maxlen = 0

Why Not to Use Random in ViciDial

Run a call distribution test:

# Generate 100 test calls to random queue
for i in {1..100}; do
  asterisk -rx "queue add member SIP/test$i to testing_queue"
done

Check distribution:

SELECT user_extension, COUNT(*) FROM vicidial_closer_log 
WHERE queue_name = 'testing_queue' 
GROUP BY user_extension;

Result: Expect uneven distribution. One agent may get 40+ calls while another gets 10.

Fewest-Calls Ring Strategy

Routes calls to the agent who has handled the fewest calls (all-time or in a configurable interval).

When to Use Fewest-Calls

When NOT to Use Fewest-Calls

Fewest-Calls Configuration

[blended_queue]
type = queue
strategy = fewest-calls
members = SIP/6001,SIP/6002,SIP/6003,SIP/6004,SIP/6005
timeout = 20
retry = 5
maxlen = 0
announce-frequency = 60
announce-holdtime = yes
joinempty = yes
leavewhenempty = yes

With fewest-calls, if call counts are:

The next call routes to SIP/6003.

Monitoring Fewest-Calls Distribution

Check call counts in real time:

asterisk -rx "queue show blended_queue"

Log calls per agent per hour to verify algorithm:

SELECT 
  user_extension,
  DATE_FORMAT(call_date, '%Y-%m-%d %H:00:00') as hour,
  COUNT(*) as calls
FROM vicidial_closer_log
WHERE queue_name = 'blended_queue'
  AND call_date >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY user_extension, hour
ORDER BY hour DESC, calls DESC;

Longest-Idle Ring Strategy

Routes calls to the agent idle the longest. Critical for preventing agent burnout and managing call pacing.

When to Use Longest-Idle

When NOT to Use Longest-Idle

Longest-Idle Configuration

[predictive_queue]
type = queue
strategy = longest-idle
members = SIP/7001,SIP/7002,SIP/7003,SIP/7004,SIP/7005,SIP/7006
timeout = 30
retry = 5
maxlen = 0
announce-frequency = 120
announce-holdtime = yes
joinempty = yes
leavewhenempty = yes
wrapuptime = 30

The wrapuptime = 30 parameter tells Asterisk an agent needs 30 seconds between calls. Longest-idle respects this.

Verifying Idle Time in ViciDial

Check agent idle tracking:

SELECT 
  user_extension,
  user_name,
  status,
  last_call_time
FROM vicidial_users
WHERE active = 'Y'
ORDER BY last_call_time DESC;

Monitor idle period in real time:

watch -n 2 'asterisk -rx "queue show predictive_queue" | grep -A 50 "Members:"'

Penalty-Based Member Configuration

All strategies can incorporate member penalties. A penalty increases an agent's effective call count or idle time, effectively deprioritizing them.

Why Use Penalties

Penalty Syntax

[skilled_queue]
type = queue
strategy = rrmemory
members = SIP/8001,SIP/8002(penalty=5),SIP/8003(penalty=10),SIP/8004
timeout = 25
retry = 5
maxlen = 0

SIP/8001 (penalty=0, default): Highest priority SIP/8002 (penalty=5): Medium priority SIP/8003 (penalty=10): Lowest priority (used only if others unavailable) SIP/8004 (penalty=0): Equal priority to 8001

Dynamic Penalty in ViciDial

Adjust penalties without reloading config:

asterisk -rx "queue remove member SIP/8003 from skilled_queue"
asterisk -rx "queue add member SIP/8003(penalty=15) to skilled_queue"

Verify:

asterisk -rx "queue show skilled_queue" | grep -A 30 "Members:"

Configuring Queue Strategy in ViciDial

Via extensions-vicidial.conf

The authoritative configuration location for production ViciDial:

[vicidial_queues]
exten => 300,1,Answer()
exten => 300,n,Queue(inbound_queue,t)
exten => 300,n,Hangup()

[general]
persistmembers = yes
autofill = yes

[inbound_queue]
type = queue
strategy = rrmemory
members = SIP/2001,SIP/2002,SIP/2003,SIP/2004
timeout = 25
retry = 5
maxlen = 0
announce-frequency = 60
announce-holdtime = yes
joinempty = yes
leavewhenempty = no

Applying Configuration Changes

Reload without dropping calls:

asterisk -rx "core reload"

Verify queue loaded correctly:

asterisk -rx "queue show inbound_queue"

ViciDial Web Admin Configuration

Navigate to /vicidial/admin.phpSystem SettingsQueues (if available in your version).

Most modern ViciDial installations manage queues via extensions-vicidial.conf, but older versions (2.10 and earlier) may have GUI queue management. Always verify the loaded config:

grep -n "strategy" /etc/asterisk/extensions-vicidial.conf | head -20

Performance Considerations

CPU and Memory Impact

Different strategies have different overhead:

Strategy CPU Cost Memory Cost Best For
linear Very Low Minimal Small teams
rrmemory Low Minimal Production ViciDial
random Very Low Minimal Testing
fewest-calls Medium Medium Large centers
longest-idle Medium Medium Predictive dialers

Scaling Considerations

For large contact centers:

Monitoring Queue Performance

Create a monitoring script to track strategy effectiveness:

#!/bin/bash
# /usr/local/bin/monitor_queues.sh

LOGFILE="/var/log/queue_monitor.log"

while true; do
  TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
  
  echo "=== $TIMESTAMP ===" >> $LOGFILE
  asterisk -rx "queue show" >> $LOGFILE 2>&1
  
  echo "" >> $LOGFILE
  sleep 300  # Check every 5 minutes
done

Run in background:

nohup /usr/local/bin/monitor_queues.sh > /dev/null 2>&1 &

Ring Strategy Selection Matrix

Use this matrix to pick the right strategy for your scenario:

SCENARIO                          RECOMMENDED STRATEGY    BACKUP
────────────────────────────────────────────────────────────────────
Small inbound (< 5 agents)        linear                  rrmemory
Medium inbound (5-20 agents)      rrmemory                rrmemory
Large inbound (20+ agents)        rrmemory + penalties    fewest-calls
Predictive dialer                 longest-idle            rrmemory
Blended (inbound + outbound)      rrmemory or fewest      longest-idle
Skill-based routing               linear + penalties      rrmemory
Multi-queue agents                rrmemory (mandatory)    N/A
Testing/Demo                      random or linear        N/A
High compliance requirements      longest-idle            rrmemory

Troubleshooting Ring Strategy Issues

Symptom: Uneven Call Distribution

Cause: Wrong strategy or penalty misconfiguration

Diagnosis:

# Check queue strategy
asterisk -rx "queue show yourqueue" | grep Strategy

# Check member penalties
asterisk -rx "queue show yourqueue" | grep -A 50 "Members:"

Solution:

If using linear and distribution is uneven, switch to rrmemory:

[yourqueue]
strategy = rrmemory

Reload and verify:

asterisk -rx "core reload"
asterisk -rx "queue show yourqueue"

Symptom: Agents Sitting Idle While Calls Queue

Cause: Strategy doesn't match agent availability state, or agent status is stuck

Diagnosis:

# Check actual extension status
asterisk -rx "core show hints | grep SIP/2001"

# Check if agent is truly available
asterisk -rx "sip show peers | grep 2001"

# Check queue log for routing decisions
tail -50 /var/log/asterisk/queue_log

Solution:

Verify agent is actually available in Asterisk state machine:

asterisk -rx "device state list | grep SIP/2001"

If stuck NOT_INUSE when agent is on call, restart agent phone or kickout stale session:

asterisk -rx "sip notify check-sync SIP/2001"

Symptom: Strategy Changed But Old Behavior Persists

Cause: Config reload didn't take effect, or persistmembers saved old config

Diagnosis:

# Verify which config is loaded
asterisk -rx "module show like queue"

# Check persistent members file
ls -la /var/spool/asterisk/outgoing/
cat /var/spool/asterisk/outgoing/queue_members.conf 2>/dev/null

Solution:

Clear persistent member cache:

asterisk -rx "queue reset stats"

If that doesn't work, rebuild completely:

# Backup current config
cp /etc/asterisk/extensions-vicidial.conf /etc/asterisk/extensions-vicidial.conf.backup

# Remove persistent files
rm -f /var/spool/asterisk/outgoing/queue_members.conf

# Full restart Asterisk (careful in production)
systemctl restart asterisk

# Verify new strategy
asterisk -rx "queue show yourqueue" | grep Strategy

Symptom: High CPU Usage After Strategy Change

Cause: fewest-calls or longest-idle causing database queries per call

Diagnosis:

# Check CPU
top -b -n 1 | grep asterisk

# Check Asterisk process details
ps aux | grep asterisk | grep -v grep

# Monitor Asterisk queue processing
asterisk -rx "core show profile" | grep Queue

Solution:

If CPU spike correlates with fewest-calls strategy, downgrade to rrmemory:

# Change from
strategy = fewest-calls

# To
strategy = rrmemory

Reload and monitor:

asterisk -rx "core reload"
watch -n 1 'top -b -n 1 | grep asterisk'

Symptom: Random Strategy Causing Call Distribution Complaints

Cause: Random legitimately causes uneven distribution; agents perceive unfairness

Diagnosis:

Run hourly distribution report:

SELECT 
  user_extension,
  COUNT(*) as total_calls,
  ROUND(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM vicidial_closer_log WHERE queue_name = 'yourqueue' AND call_date >= DATE_SUB(NOW(), INTERVAL 1 HOUR)), 2) as percent
FROM vicidial_closer_log
WHERE queue_name = 'yourqueue'
  AND call_date >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
GROUP BY user_extension
ORDER BY total_calls DESC;

Solution:

Switch to rrmemory:

strategy = rrmemory

Re-run report after 1 hour—distribution will be nearly identical across agents.

Advanced: Custom Queue Logic via AGI

For edge cases where built-in strategies don't fit, use Asterisk Gateway Interface (AGI) to implement custom routing:

<?php
// /var/lib/asterisk/agi-bin/custom_route.php

$agi = new AGI();
$queue = $agi->request['agi_arg_1'];

// Fetch agents ordered by custom logic
$mysqli = new mysqli('localhost', 'root', 'password', 'asterisk');

$result = $mysqli->query("
  SELECT user_extension 
  FROM vicidial_users
  WHERE active = 'Y'
    AND user_group = '$queue'
  ORDER BY calls_today ASC
  LIMIT 1
");

$row = $result->fetch_assoc();
$target = $row['user_extension'];

// Route call to chosen agent
$agi->exec('Dial', "SIP/$target");
?>

Call from extensions-vicidial.conf:

exten => 300,1,AGI(custom_route.php,inbound_queue)
exten => 300,n,Queue(inbound_queue,t)

This is overkill for 99% of installations but useful for complex skill-based routing.

Summary

Ring strategy is the invisible backbone of queue performance. Choose wisely:

  1. For production ViciDial: Use rrmemory (round-robin queue member) as your default. It's battle-tested, fair, and lightweight.

  2. For predictive dialers: Use longest-idle to prevent agent burnout and control call pacing.

  3. For skill-based routing: Start with linear or rrmemory plus penalties to prioritize experienced agents.

  4. For large centers (50+ agents): Monitor fewest-calls as an alternative, but verify CPU impact first.

  5. Never use random in production—it's called "random" for a reason.

Always verify configuration loaded correctly with asterisk -rx "queue show yourqueue", monitor distribution with database queries, and adjust penalties if specific agents need deprioritization.

The right ring strategy keeps your agents happy, your customers served quickly, and your contact center running efficiently. Get this right, and you'll never think about it again.

Need expert help with your setup?

VoIP infrastructure consulting, AI voice agent integration, monitoring stacks, scaling — I've done it all in production.

Get a Free Consultation