---
title: >-
  Tune voice apps that hold up across Kenya: the network realities every
  developer must know
description: >-
  Ground-level briefing on Safaricom, Airtel, and Telkom routing, 2G fallback
  zones, inter-carrier latency, and what it means for IVR tuning.
summary: >-
  Safaricom holds ~65% subscriber share and peers directly with Sautikit at ~8
  ms. Airtel and Telkom route via KIXP at ~15–20 ms. 2G zones in Coast and
  Northern Kenya need GetDigits timeout ≥10 s.
date: 2026-07-03T00:00:00.000Z
type: blog
---


## Summary

A voice application that works perfectly in Nairobi CBD can fail unpredictably in Kisumu, Mombasa, or Nakuru. Kenya's three main mobile networks route calls differently, use different interconnect paths to Sautikit, and expose callers to different codec profiles. This post is a technical briefing covering what those differences mean for IVR timeout tuning, codec selection, retry limits, and call quality monitoring.

## Kenya's three major mobile networks

Kenya has three licensed mobile network operators:

- **Safaricom**: approximately 65% subscriber market share (Communications Authority of Kenya, Q1 2026 sector statistics). 4G coverage across Nairobi, Mombasa, Kisumu, and most county capitals; 3G in most peri-urban areas; 2G base coverage across the country.
- **Airtel Kenya**: approximately 25% subscriber market share. 4G concentrated in Nairobi and major towns; 3G in secondary towns; 2G in rural areas. Strong in the Western Kenya counties (Kisumu, Kakamega, Busia).
- **Telkom Kenya**: approximately 10% subscriber market share. 4G in Nairobi CBD and select Mombasa areas. Largely 3G/2G outside Nairobi. Stronger in government institutional lines than consumer mobile.

Understanding which network your users are on changes your application configuration. A DTMF timeout that works for a Nairobi Safaricom 4G subscriber will generate "no input" errors for a Telkom user in Nakuru on 3G.

## Safaricom's dominance and the direct peering benefit

All Sautikit local numbers (both Nairobi `020` landlines and `07xx` mobile numbers) are interconnected with Safaricom via a direct peering arrangement. This means Safaricom-to-Safaricom calls on Sautikit never leave Safaricom's core network.

The practical result: a Safaricom mobile subscriber calling your Sautikit `020` or `07xx` number sees approximately 8 ms one-way latency. Compare this to the ~45 ms you get for a cross-carrier call that transits an interconnect PoP. For IVR applications, this 37 ms difference is negligible in human perception, but it does mean your Safaricom users will have slightly tighter DTMF detection timing than cross-carrier users.

You can verify the routing path from a SIP trace. On a Safaricom-originated call, the `Via` headers in the SIP `INVITE` will show only Safaricom and Sautikit hops: no third-party transit carrier appears in the SIP routing path.

## Airtel and Telkom: KIXP interconnect

Airtel Kenya and Telkom Kenya interconnect with Sautikit via the Kenya Internet Exchange Point (KIXP), operated by TESPOK at their Nairobi facility. KIXP provides a local IP transit layer that keeps inter-carrier traffic within Kenya rather than routing it internationally.

KIXP-routed calls add a fixed overhead of approximately 15–20 ms compared to the direct Safaricom peering path. This is still far below the 150 ms ITU-T G.114 recommendation. Calls from Airtel or Telkom numbers are affected; calls from Safaricom numbers are not.

A SIP trace (`sngrep` or `tcpdump -i any port 5060`) on an Airtel-originated call will show KIXP's AS (Autonomous System) in the routing path:

```
INVITE sip:+254700000001@sip.sautikit.com
Via: SIP/2.0/UDP airtel-sip-gw.airtelkenya.net;branch=...
Via: SIP/2.0/UDP kixp-sbc.tespok.or.ke;branch=...
Via: SIP/2.0/UDP sip.sautikit.com;branch=...
```

The important takeaway: KIXP routing is local. Some international voice API providers route cross-carrier Kenyan calls via their London or Dublin SIP proxies and back, adding 200+ ms. Sautikit stays on the KIXP path, keeping all Kenya-to-Kenya traffic in Kenya.

## 2G fallback zones: where coverage thins

Coverage maps are optimistic. Real-world 4G coverage in Kenya breaks down quickly outside county capitals:

**Known 2G-dominant zones** (Q2 2026):
- Northeastern Kenya: Mandera, Wajir, Garissa counties; mostly 2G, some 3G in county capitals
- Coastal rural areas: Lamu, Tana River, Kilifi hinterland; 3G at coast, 2G 5+ km inland
- Northern Rift Valley: Turkana, West Pokot, Samburu; 2G with significant coverage gaps
- Parts of Nyanza rural: Homa Bay, Migori; 2G prevalent beyond Homa Bay town

In 2G-dominant zones, the effective voice codec is AMR-NB (Adaptive Multi-Rate Narrowband) at 12.2 kbps. This is the codec floor on Safaricom 2G. AMR-NB is designed for voice intelligibility, not for high-fidelity audio or DTMF tone preservation.

## What 2G means for in-band DTMF

AMR-NB at 12.2 kbps compresses audio in ways that degrade DTMF tones. The lower-frequency component of DTMF tones (697 Hz, 770 Hz for row 1 and 2 keys) suffers more compression artefacts than the higher-frequency component. This causes the detection algorithm to miss presses on keys 1, 2, 3, and 4 at a measurable rate on 2G.

Sautikit uses RFC 4733 out-of-band DTMF by default: DTMF events are sent as separate RTP packets (payload type 101) that travel independently of the voice codec. This eliminates the 2G in-band detection problem for SIP-capable clients. For PSTN calls through Safaricom's GSM interconnect, however, RFC 4733 is not available: the PSTN path converts out-of-band DTMF back to in-band tones at the PSTN gateway.

The consequence: IVR applications serving 2G callers via standard PSTN should increase `timeout` and provide audible feedback on each key press:

```json
{
  "actions": [
    {
      "say": {
        "text": "Press 1 for Swahili. Press 2 for English. Then press the hash key.",
        "language": "sw-KE"
      }
    },
    {
      "getDigits": {
        "numDigits": 1,
        "timeout": 10000,
        "finishOnKey": "#",
        "action": "https://your-server.example.com/ivr/menu"
      }
    }
  ]
}
```

Setting `timeout` to 10 000 ms (10 seconds) instead of the default 5 000 ms measurably reduces "no input" webhook events for 2G callers. This is validated in deployment data from Kenyan IVR services with rural coverage.

## Network-zone-aware configuration pattern

Rather than applying one configuration globally, detect the caller's network from their E.164 prefix and apply zone-appropriate settings:

```js
function getNetworkConfig(e164) {
  // Returns IVR configuration tuned for the caller's likely network.
  // E.164 prefix detection based on CA Kenya number plan.
  let carrier;
  if (e164.startsWith("+2547")) {
    carrier = "safaricom";
  } else if (e164.startsWith("+2541")) {
    carrier = "airtel";
  } else if (e164.startsWith("+25477") || e164.startsWith("+25476")) {
    carrier = "telkom";
  } else {
    carrier = "unknown";
  }

  // Safaricom: direct peering, typically 4G/3G in urban areas
  if (carrier === "safaricom") {
    return { digitsTimeoutMs: 7000, sayPauseMs: 500 };
  }

  // Airtel: KIXP routing, mix of 4G/3G/2G
  if (carrier === "airtel") {
    return { digitsTimeoutMs: 8000, sayPauseMs: 700 };
  }

  // Telkom or unknown: conservative settings
  return { digitsTimeoutMs: 10000, sayPauseMs: 1000 };
}
```

This pattern is a heuristic, not a guarantee: a Safaricom subscriber roaming on 2G in Garissa still gets the Safaricom config. For applications with a known rural user base, apply the conservative 10-second timeout universally.

## Inter-carrier routing: the hidden call setup delay

Beyond audio latency, inter-carrier calls have higher call setup delay (the time from `POST /v1/calls` to the remote phone ringing). Sautikit's outbound calls to Safaricom numbers typically set up in 1.5–2.5 seconds. Calls to Airtel numbers via KIXP add 0.5–1 second to setup time. Calls to Telkom numbers can add 1–2 seconds.

This matters for time-sensitive flows like M-Pesa payment confirmation calls, where a user expects the confirmation within a few seconds of payment. If your Airtel users consistently report that confirmation calls arrive late, inter-carrier setup delay is the likely cause, not your application latency.

You can measure setup delay by comparing `created_at` and `answered_at` timestamps in Sautikit call records:

```bash
curl -s "https://api.sautikit.com/v1/calls?direction=outbound&limit=100" \
  -H "Authorization: Bearer $SAUTIKIT_API_KEY" \
  | jq '[.calls[] | {
      carrier: (if .remote_e164 | startswith("+2547") then "safaricom"
                elif .remote_e164 | startswith("+2541") then "airtel"
                else "other" end),
      setup_ms: ((.answered_at // .completed_at) | if . then
        ((. | strptime("%Y-%m-%dT%H:%M:%SZ") | mktime) -
         (.created_at | strptime("%Y-%m-%dT%H:%M:%SZ") | mktime)) * 1000
        else null end)
    }] | group_by(.carrier) | map({carrier: .[0].carrier, avg_setup_ms: (map(.setup_ms | select(. != null)) | add / length)})'
```

## Monitoring network-specific call quality in Sautikit CDRs

Sautikit call detail records include `remote_e164`, which you can use to segment quality metrics by carrier. Key signals to monitor per carrier:

- **Answer rate**: percentage of outbound calls that reach `answered` state vs `no-answer` or `busy`. Telkom numbers have lower average answer rates.
- **Duration distribution**: very short calls (&lt;5 s) on Airtel or Telkom may indicate call setup issues rather than genuine short calls.
- **Failed rate**: `GET /v1/calls/stats?group_by=carrier`; a spike in failures on one carrier indicates an interconnect issue rather than an application bug.

Export CDR data for analysis:

```bash
curl -s "https://api.sautikit.com/v1/calls?from=2026-07-01&to=2026-07-25&limit=1000" \
  -H "Authorization: Bearer $SAUTIKIT_API_KEY" > calls-july.json
```

Then use `jq` or load into DuckDB for carrier-segment analysis. A useful dashboard metric is answer rate per carrier per hour: Safaricom answer rates drop slightly during commute hours (7–9 AM, 5–7 PM) due to network congestion, but the drop is less severe than on Airtel/Telkom where the network is thinner.

## Summary of recommended settings by zone

| Zone | Carrier | Codec floor | `GetDigits` timeout | Notes |
|---|---|---|---|---|
| Nairobi CBD | Safaricom | G.711/Opus | 5 000 ms | Direct peering, ~8 ms latency |
| Nairobi CBD | Airtel/Telkom | G.711 | 6 000 ms | KIXP, ~20 ms latency |
| County capitals | All | 3G/AMR-NB | 8 000 ms | Mixed coverage |
| Peri-urban | Safaricom | AMR-NB/2G | 10 000 ms | 2G fallback likely |
| Rural/remote | Any | AMR-NB 2G | 10 000 ms | Use `finishOnKey: "#"` |

If a 2G caller can't reliably complete a voice IVR, reach them on another channel: [Helloduty](https://helloduty.com) adds SMS, WhatsApp, USSD, and a human-agent desk alongside your Sautikit voice flows.

## Get started

1. [Create a Sautikit workspace](/) and claim a phone number.
2. Top up over **M-Pesa**: KES billing, no card.
3. Set your `getDigits` timeout by zone (10 000 ms for rural/2G) and place a test call to confirm DTMF detection.

**[Start with Sautikit →](/)** &nbsp;·&nbsp; **[See pricing →](/pricing)** &nbsp;·&nbsp; **[Need SMS, WhatsApp & an agent desk? Helloduty →](https://helloduty.com)**

## Next steps

- [Number types and Nairobi PoP routing](/developers/concepts/numbers)
- [GetDigits verb: timeout and finishOnKey configuration](/developers/concepts/voice-actions)
- [Pricing: per-minute rates and inbound vs outbound](/pricing)
