The Voice AI Load Test Most Teams Forget: Call Closure


Most voice AI load tests answer one question: at peak volume, do calls connect? A second question matters just as much: when a call is over, does it actually end?
A call that never closes keeps holding a concurrency slot on the voice AI platform, a channel on your SIP trunk, and often a port or seat on your contact center platform. Nobody is talking on it. At peak, a few dozen of these can push you into your limits while call volume looks normal.
This guide covers the closure side of load testing. For latency, accuracy, and throughput under load, see our guide to voice agent load testing.
A call is closed when every leg of it has been released by every system it passed through: the caller's leg, any transfer leg, and the AI agent's session.
On a SIP call, closure is a signaling event. One side sends a BYE message, the other side answers 200 OK, and each system frees the channel. A leg that rang but was never answered is cleared with a CANCEL.
For a voice AI deployment, three things have to be true:
In Retell, a finished call has a status of ended and a disconnection reason such as user_hangup, agent_hangup, or call_transfer. A call still in progress has a status of ongoing, and ongoing calls are what count toward your current concurrency.
A transfer turns one call into two or more legs, often across two platforms, and a hang-up on one leg has to reach the others. When that signal is lost or ignored, a leg stays up with nobody on it.
Patterns to check in your setup:
For the caller experience of each type, see how call transfers work between AI voice agents and human teams and our warm transfer guide.
One concurrency slot for as long as it stays open. Concurrency counts simultaneous active calls, and an empty call counts the same as a real one.
The math is simple: extra open calls at any moment = calls per hour that fail to close × hours each one stays open.
| Scenario (illustration, not a measurement) | Failed closures per hour | How long each stays open | Extra open calls at any moment |
|---|---|---|---|
| Occasional glitch, short silence timeout | 6 | 10 minutes | 1 |
| Occasional glitch, only the 1 hour duration cap | 6 | 60 minutes | 6 |
| One misconfigured transfer route carrying 60 transfers per hour | 60 | 60 minutes | 60 |
The third row is how teams end up with dozens of phantom calls at peak: one configuration problem, such as hang-ups not forwarded across a transfer, applied to every transferred call.
That capacity is not free. On Retell, the first 20 concurrent calls are included and additional capacity is $8 per concurrent call per month (see pricing). When a workspace reaches its limit, new inbound calls wait about 40 seconds for a free slot, then go to the phone number's fallback number if one is set, or end with concurrency_limit_reached. New outbound calls are rejected unless concurrency burst is turned on. At peak, stuck calls turn real callers away.
The same math applies to trunk channels and contact center licenses, which the voice AI platform cannot see.
End every call on purpose, through every ending path, at your peak rate, then prove that every system's active call count returns to zero.
| Ending path | How to trigger it in the test | Expected result on the AI side | Also confirm |
|---|---|---|---|
| Caller hangs up mid-conversation | Test caller drops at a random point | ended, user_hangup | Carrier and contact center channel released |
| Agent ends the call | Script a goodbye that meets the End Call tool's condition | ended, agent_hangup | Your platform receives the BYE and frees the port |
| Cold transfer, then caller hangs up | Transfer, then drop the caller | ended, call_transfer | Destination leg also released |
| Cold transfer, then destination hangs up | Transfer, then drop the destination | ended, call_transfer | Caller leg also released |
| Warm transfer connects, then either side hangs up | Answer at the destination, then drop one side | transfer_bridged, then transfer_ended webhooks | No leg left on hold |
| Transfer never answered | Let the destination ring past the transfer ring duration | transfer_cancelled webhook | CANCEL sent; no ringing leg left behind |
| Caller hangs up while on hold | Drop the caller during a warm transfer | Call ends | Consultation leg to the destination torn down |
| Silent line | Test caller stays silent | ended, inactivity | Time to close matches your silence setting |
Transfer webhooks are off by default. Add transfer_started, transfer_bridged, transfer_cancelled, and transfer_ended to the agent's webhook events for the test.
After the peak ramp, stop placing new calls and watch the counters fall. Poll Retell's Get Concurrency API, which returns current_concurrency (the number of ongoing calls), every few seconds. It should reach zero within the length of your longest scripted call. Check your SBC, contact center, and trunk counts at the same moments. Any counter that stays high is the leak, and the system holding it tells you which side is not releasing.
call_started webhook should have a matching call_ended. Every transfer_started should have a transfer_ended or transfer_cancelled.call_status filter of ongoing to find stragglers.Watch for concurrency that stays high when volume drops, more calls closed by timeouts, and transfer failures.
concurrency_used (peak concurrent calls in a window) alongside call_count (calls that ended in the window). If concurrency climbs while ended calls stay flat, calls are not ending.transfer_call_failure_count.inactivity or max_duration_reached after transfers means the backstops, not the hang-ups, are closing your calls.Timeouts. They do not fix broken signaling, but they cap how long a stuck call can hold a slot.
| Setting | Retell default | Range | Why it matters for closure |
|---|---|---|---|
| End Call tool | Off: the agent does not end calls on its own | Conditions you define | Without it, calls end only when the caller hangs up or a timeout fires |
| End call on silence | 10 minutes | 10 seconds minimum | A dead, silent leg is closed after this long |
| Max call duration | 1 hour | 1 minute to 2 hours | The last-resort cap on any call |
| Transfer ring duration | Agent ring duration, 30 seconds | 5 to 90 seconds per transfer | Unanswered transfer attempts give up |
| Warm transfer wait for agent answer | 30 seconds | Configurable | Limits time spent waiting for a human at a queue |
Set the silence and duration limits close to your real call lengths. With the defaults, a dead leg that stays silent can hold a slot for 10 minutes, and one the silence timer does not catch can hold it for up to an hour.
Get written answers before launch:
Treat "concurrency returns to zero after the test" as a pass or fail criterion. Run the closure matrix and drain test before launch and again after any change to transfer settings, numbers, or call routing.
Retell gives you the pieces: cold, warm, and agentic warm call transfer with ring and wait timeouts, transfer webhooks, per-call disconnection reasons, packet captures, a live concurrency API, and alerts on concurrency and transfer failures. If you are planning a contact center rollout with high peak concurrency, the Retell Enterprise plan adds a high cap on concurrent calls and dedicated support.
Related reading: Why load tests must follow the real call path, the outbound phone number checklist, and more guides in the Retell Learn hub.
See how much your business could save by switching to AI-powered voice agents.
Total Human Agent Cost
AI Agent Cost
Estimated Savings
A Demo Phone Number From Retell Clinic Office

Start building smarter conversations today.




