What a queue does
A queue holds callers in line and distributes them to agents according to a rule you choose. That rule — the ring strategy — is the single most consequential setting, because it decides which agent's phone rings, and getting it wrong produces the two classic complaints: one agent taking every call while others sit idle, or every phone in the building ringing on every call.
Queues are configured in queues.conf, with each queue defined in its own section.
The ring strategies
Asterisk offers several, and the differences are not cosmetic:
- ringall — rings all available members until one answers. This is the default. Simple and fast to answer, but it means every phone rings constantly, which agents dislike, and it tends to reward whoever is quickest on the button rather than distributing work.
- leastrecent — rings the member who was least recently called by this queue. A reasonable fairness rule, though "least recently called" is not the same as "least busy": an agent who took one long call may look more available than one who handled several short ones.
- fewestcalls — rings the member with the fewest completed calls from this queue. Balances call count, which again is not the same as balancing workload if call durations vary widely.
- rrmemory — round robin with memory. It remembers the last member it tried, so the next call starts with the agent after the last one who answered. With three agents, a call ringing 1→2 (answered) is followed by one ringing 3→1, then 2→3→1, and so on. This is usually the sensible default for an even distribution.
- linear — rings members strictly in the order listed in the configuration file. Useful for deliberate tiering: senior agents first, overflow second.
- random — rings a random available member.
- roundrobin — the older round-robin implementation, deprecated since Asterisk 1.4 in favour of
rrmemory. Do not use it in new configurations.
For most contact centres wanting fair distribution, rrmemory is the right starting point. Use linear when call priority by skill matters more than fairness, and ringall only for small teams where answering speed beats everything.
A working queue definition
[support]
strategy = rrmemory
timeout = 15
retry = 5
wrapuptime = 10
maxlen = 0
announce-frequency = 60
joinempty = no
leavewhenempty = yes
musicclass = default
member = PJSIP/1001
member = PJSIP/1002
member = PJSIP/1003The settings that most often need attention:
- timeout — how long each member's phone rings before moving on. Fifteen seconds is a common balance; too short and agents cannot reach the handset, too long and callers wait through dead air.
- retry — the pause before trying the next member after a failed attempt.
- wrapuptime — how long after finishing a call before that agent is offered another. Skipping this is a frequent mistake: without it, agents get a new call the instant they hang up, with no time to complete notes.
- maxlen — the maximum number of waiting callers;
0means unlimited. - joinempty and leavewhenempty — what happens when no members are available. Setting
joinempty = nostops callers entering a queue with nobody to answer, andleavewhenempty = yesejects those already waiting if the last agent disappears. Get these wrong and callers sit listening to hold music that will never end — one of the worst experiences a phone system can produce.
Calling the queue from the dialplan
Queues are entered with the Queue() application:
exten => 200,1,Answer()
same => n,Queue(support,tT,,,300)
same => n,Voicemail(200@default)
same => n,Hangup()The option letters control call behaviour. Commonly used ones include t and T to permit transfers by the called member or the caller, r to play ringing instead of music on hold, n to prevent retrying members on timeout, m to set a specific music-on-hold class, and x or X to enable recording via MixMonitor. There are also Gosub hooks (b, B) for running dialplan logic before outgoing calls, and options for parking and hangup handling.
The final numeric argument is the overall queue timeout in seconds — the point at which the caller stops waiting and falls through to the next dialplan step, which is where you put voicemail. Always provide that fallback: a queue with no exit strands callers when nobody answers.
Static vs dynamic members
Members listed in queues.conf are static — always in the queue. That is fine for a small fixed team but poor for shift work, since a logged-off agent's phone still rings.
Dynamic members log in and out at will using AddQueueMember() and RemoveQueueMember() from the dialplan, usually behind a feature code. This is how any real contact centre operates, and it makes queue statistics meaningful because idle time reflects agents actually present.
Inspect the live state from the CLI:
asterisk -rx "queue show support"That shows waiting callers, each member's status, and completed call counts — the first thing to check when a queue is not behaving as expected.
Common mistakes
- No wrapuptime. Agents get slammed with back-to-back calls and cannot finish notes.
- Static members for shift-based teams. Phones ring for people who went home.
- joinempty left permissive. Callers enter a queue with no agents and wait indefinitely.
- No dialplan fallback after Queue(). The caller reaches the end of the queue and the call simply ends.
- ringall on a large team. Every phone rings on every call and agents stop noticing.
- Using roundrobin. Deprecated;
rrmemoryreplaced it.
Frequently asked questions
Which queue strategy should I use?
rrmemory for fair distribution in most contact centres. linear when you want a deliberate order such as senior agents first. ringall only for small teams prioritising speed of answer.
Why does one agent get all the calls?
Almost always ringall — every phone rings and the fastest wins every time. Switch to rrmemory for even distribution.
What is the difference between static and dynamic queue members?
Static members are defined in queues.conf and are always in the queue. Dynamic members log in and out at runtime via AddQueueMember(), which is what shift-based teams need.
Why do callers wait forever with nobody to answer?
Check joinempty and leavewhenempty. With permissive settings, callers can enter and remain in a queue that has no available members.