---
title: "Latency you can actually feel"
summary: "The network is rarely the slow part. Template approval, queueing and carrier acceptance dominate wall-clock time, and only one of them is under your control."
canonical: https://cpaas.co/en/insights/latency-you-can-actually-feel
kind: article
depth: applied
origin: original
published: 2026-07-05T11:34:07.986Z
updated: 2026-09-08T11:34:08.153Z
topics: ["Architecture", "Messaging", "Analytics"]
language: en
---
# Latency you can actually feel

> **Interactive figure — latency-race.** Run it. Then notice that the differences between channels are smaller than the difference between a well-run send path and a badly-run one.
> Available at https://cpaas.co/en/insights/latency-you-can-actually-feel

## Where the time actually goes

For a one-time code — the most latency-sensitive message most businesses send — the budget usually looks nothing like people expect:

- **Your own processing.** Deciding to send, rendering, checking consent. Typically tens of milliseconds, occasionally seconds if the consent check hits a cold cache or a synchronous third-party call.
- **Provider acceptance.** The API call. Fast, and the part everyone measures.
- **Queueing.** The part nobody measures. Under load, or when a route is congested, this dominates everything else.
- **Carrier handling.** Out of your control, variable by market, and the reason the same code takes two seconds in one country and twenty in another.
- **Handset display.** Doze modes, battery optimisation and notification throttling on the device itself.

The API call — the only segment most teams instrument — is frequently the smallest term.

The part you control is the smallest part, which is why tuning it first is such a common and such an expensive mistake.

```diagram:bars
# A one-time code, from button press to handset, in milliseconds
Your application | 40 | Generating the code, writing it down, calling the send function.
Provider API | 120 | Accepting the request and queueing it. The only leg with a published SLA.
Aggregator hop | 300 | Where a partner route rather than a direct one shows up as time.
Carrier queue | 1400 | Not yours, not your provider's, and highly variable by market and hour.
Handset delivery | 900 | Radio conditions, device state, whether the phone is asleep.
> Roughly 6% of the total is code you can optimise. The other 94% is chosen at procurement, not at runtime.
```

## Three things that actually help

**Measure end to end, not to the API response.** A timestamp when you decided to send and a timestamp when the delivery receipt arrives. Everything in between is one number, and it is the number the customer experiences.

**Watch the tail, not the mean.** Nobody complains about the median. They complain about the 99th percentile, and in messaging the tail is very long — a mean of two seconds routinely hides a p99 in the tens.

**Do the slow work before you need to send.** Consent state, template approval, route selection: precompute what you can. The send path should be short, and it should not be the first place a cache miss shows up.

**Choose the route, not the code path.** A direct operator connection in-market beats every optimisation you can make above it, by an order of magnitude. This is a purchasing decision that presents itself as an engineering one.

**Send before you need to.** For anything predictable — a scheduled reminder, a pre-authorised code — the latency budget starts when you decide, not when the user waits. Most of the time pressure in these systems is self-inflicted.

**Stop measuring the average.** The average is fine and nobody experiences it. The 95th percentile is the number a customer service team feels, and the gap between the two is usually the whole story.

## The design consequence for codes

If a code has to arrive in seconds, do not make its delivery the only path forward. Offer a fallback the user can trigger — resend, a different channel, an in-app confirmation. The cost of building that is far lower than the conversion lost to a carrier having a bad afternoon in a market you cannot see into.

```diagram:flow
# A code screen that survives a slow network
Show the wait | A visible timer beats a spinner. The user needs to know how long is normal.
Offer the alternative early | A "call me instead" route at ten seconds, not at sixty. Voice arrives on a different path.
Never expire before arrival | A code valid for sixty seconds on a network that takes eight is a support ticket waiting to happen.
Allow one resend, then change route | The second attempt down the same slow path is not a different attempt.
Log the round trip | Per market, per hour. This is how you find out that Tuesday afternoons in one country are broken.
> Every step here is interface work. None of it makes the network faster, and all of it makes the wait survivable.
```

## And the one about retries

Retry with backoff and a cap, and make retries idempotent from the recipient's point of view. The failure mode here is not a slow message; it is four copies of the same code arriving at once, two of which are already invalid. That is worse than the original problem, and it is entirely self-inflicted.

A retry that goes down the same route that just failed is not a retry, it is a second attempt at a failure. It doubles the load on the path that is already struggling and roughly doubles the time before the user gets anything.

Retry on a different route or a different channel, or do not retry at all — tell the user instead. And put a ceiling on it: three attempts, then stop and offer something else. Systems without a ceiling produce the outage-day pattern where every user is retrying and nothing gets through.

## What to take away

Almost none of the latency is yours. Buy the route, send early where you can, measure the 95th percentile per market, design the interface for the slow case, and never retry down the path that just failed.

---

Published by the company behind five products in this category. Those products appear in this site's directory alongside competitors under the same published criteria and are labelled as its own. Editorial content does not recommend them.
