Who does what
The split follows what each project does best. Kamailio is a SIP proxy and registrar. It handles lots of transactions for very little memory, and it never touches RTP unless you add rtpengine. FreeSWITCH is a back-to-back user agent. It anchors media, so it can play prompts, mix conferences, record and transcode.
- Kamailio:
registrar/usrlocfor registrations,auth_dbfor digest auth,dispatcherfor load balancing across media servers,pikeandhtablefor rate limiting and bans,permissionsfor trunk ACLs, andtmfailure routes for retries. - FreeSWITCH: IVR menus,
mod_conference,mod_voicemail,mod_callcenterqueues, call recording withrecord_session, and transcoding between codecs, all running onmod_sofiaprofiles that only talk to Kamailio.
A phone registers with Kamailio and never knows FreeSWITCH exists. When a call needs a feature, Kamailio relays it to a FreeSWITCH node. When FreeSWITCH needs to reach a user, it sends the INVITE back through Kamailio, which does the lookup("location").
Why one box doing both hurts
Signalling and media load grow in different ways. A REGISTER refresh or an OPTIONS keepalive costs Kamailio almost nothing. A recorded, transcoded conference leg costs FreeSWITCH real CPU and disk I/O. If one box does both, a busy conference bridge can slow down registrations. Phones then start re-registering, and the extra signalling adds even more load.
Failure works the same way. If an all-in-one server crashes, every phone loses its registration, every call drops and every feature is gone at once. Users see phones showing "No service", and the helpdesk phones are down too. With the split, losing a media node takes out only the calls on that node.
Upgrades are the third reason. FreeSWITCH releases and codec modules change more often than your edge proxy should. With the two separated, you can patch the media tier one node at a time while registrations and routing carry on untouched.
Failover that callers actually notice
Be honest about what happens. If a FreeSWITCH node dies, the calls it was anchoring are lost. Kamailio can't rescue RTP it never handled. Those callers hear the call drop. When they redial, the call lands on a healthy node and the IVR, queue or voicemail answers as normal. Phones stay registered the whole time, because registrations live in Kamailio.
For that to work, Kamailio has to notice a dead node quickly and move to the next one within the same transaction. dispatcher sends OPTIONS probes to each node and marks unresponsive ones inactive. A failure route catches the calls that were already in flight to the node when it died:
# 2 = failover support: keep the other destinations for ds_next_dst()
modparam("dispatcher", "flags", 2)
modparam("dispatcher", "ds_ping_interval", 10)
modparam("dispatcher", "ds_probing_mode", 1)
modparam("dispatcher", "ds_probing_threshold", 2)
route[TO_MEDIA] {
if (!ds_select_dst("1", "4")) {
send_reply("503", "No media servers available");
exit;
}
# 2s for a media node to send any reply, 120s once it's ringing
t_set_fr(120000, 2000);
t_on_failure("MEDIA_FAIL");
route(RELAY);
}
failure_route[MEDIA_FAIL] {
if (t_is_canceled()) exit;
if (t_check_status("5[0-9][0-9]") || (t_branch_timeout() && !t_branch_replied())) {
# no reply at all: take the node out until probing brings it back.
# a 5xx only moves this call on (a 503 may just mean "busy right now").
if (t_branch_timeout() && !t_branch_replied()) {
ds_mark_dst("ip");
}
if (ds_next_dst()) {
t_set_fr(120000, 2000);
t_on_failure("MEDIA_FAIL");
route(RELAY);
}
}
}The 2-second fr_timer suits media servers on your own network. A healthy FreeSWITCH sends 100 Trying almost immediately, so callers shouldn't sit through the 30-second default before a retry. If failover isn't happening as you expect, work through our dispatcher failover guide.
Keep related calls on the same media server
Round-robin works for calls that stand alone. Some features need several calls on the same box. Every leg of a conference has to reach the FreeSWITCH node hosting that room, otherwise you end up with two half-empty conferences that share a name. Use a hashing algorithm for those number ranges, for example ds_select_dst("2", "3") to hash over the Request-URI. Every dial-in to the same conference number then reaches the same node while it stays up.
Voicemail needs shared state instead. Picture a hosted PBX with four media nodes. A message left on node A has to be playable when the user dials in and lands on node C. That means putting the voicemail storage and mod_voicemail's database on something every node can reach. It also means routing MWI NOTIFYs back through Kamailio, so the lamp on the handset reaches the phone's registered contact.
Security belongs at the edge
Kamailio is the only thing the internet should see. Digest auth, pike flood detection, User-Agent filtering and htable bans all happen there, before any media resources are used. Our friendly-scanner guide covers the blocking rules.
On the FreeSWITCH side, firewall SIP so only the Kamailio nodes can reach it, and set apply-inbound-acl on the Sofia profile to an ACL listing those addresses. Calls from the proxy then come in already authenticated. Kamailio can pass the tenant or authenticated user as an X- header, which the dialplan reads as ${sip_h_X-Tenant}, so FreeSWITCH never has to repeat the auth work. Callers never see any of this. All they notice is that toll-fraud attempts and scanner floods don't slow down their calls.
What the ops team gets
Maintenance becomes routine instead of an out-of-hours event. To patch a media node, mark it inactive with kamcmd dispatcher.set_state i 1 sip:10.0.0.12:5060, wait for its active channel count in fs_cli to drain to zero, then upgrade and reactivate it. New calls never touch it and nobody gets cut off. Adding capacity means adding a row to the dispatcher list and running kamcmd dispatcher.reload.
You also get clearer signals when something goes wrong. Registration counts, dispatcher destination states and FreeSWITCH channel counts are separate metrics that point to separate layers. "Phones can't register" and "IVR prompts are silent" stop looking like the same incident. Both tiers have their own failure modes: NAT and SDP on the Kamailio side, and codec and RTP port ranges on FreeSWITCH. If you want a second pair of eyes on a FreeSWITCH media tier, our FreeSWITCH consultancy covers exactly that.