USSD Application Testing: Load Tests and the Tools to Use

USSD Application Testing: Load Tests and the Tools to Use

USSD application testing: a phone showing a USSD menu with every option ticked as tested, beside a load test chart where reply time stays under the limit line as virtual users ramp up

USSD application testing has two parts, and you need both before customers in Ghana start dialling your code. A functional check on real handsets shows that every menu path does what it should. USSD load testing shows that your server keeps replying quickly when many people dial at once, for example on salary day or the morning a promotion launches.

Work in this order: your own machine first, with plenty of realistic dummy data, then a staging server set up like production, watching the measures that tell you whether you are ready. This guide assumes your menu is already built and connected to Arkesel. If you are not there yet, start with our guide to build your USSD application, and for the business case behind the channel, see how businesses use USSD for interactive customer experiences.

Why should you load test a USSD application?

On USSD, your customer waits on your server at every step, inside a session with a fixed lifetime. If your server slows down when traffic rises, customers feel it on every screen, and some sessions may not finish.

Each step of a session works like this. Arkesel’s USSD API documentation says Arkesel sends every request to your endpoint URL by HTTP POST with JSON data, and expects your response in JSON. As the Arkesel USSD API page puts it, your server receives a POST request for each user interaction and responds with the next menu or a final message. The customer sees nothing new until your reply arrives.

How long does a USSD session stay open on Arkesel?

According to Arkesel, a USSD session stays open for 150 to 180 seconds, so that window is the session timeout your menu works within. The customer’s reading and typing and every one of your server’s replies must fit inside that window.

Arkesel’s documentation does not say what happens when your server slows down, but the way each step works makes the risk clear. A server that answers instantly for a handful of testers can slow down when hundreds of customers dial in the same few minutes. Each slow reply uses time the customer also needs for reading and typing, so a menu with several steps and slow replies can run out of time before the customer finishes. The customer may then dial again, adding to the load that caused the problem.

Busy moments such as salary day or a promotion launch can be planned for, so test for them before they arrive. Set your own limit for reply time from the baseline you measure locally (covered below), and aim for every reply to come back well inside the session window.

USSD request chain from the customer's handset through MTN, Telecel or AirtelTigo and Arkesel to your callback endpoint. Arkesel sends six JSON fields: sessionID, userID, newSession, msisdn, userData and network. Your reply returns all five fields every time: sessionID, userID and msisdn echoed exactly, message, and continueSession, where true waits for the next input and false ends the session. A session stays open for 150 to 180 seconds, according to Arkesel.

Start with a quick check on real handsets

Before you apply any load, confirm the menu works on the phones your customers use. Arkesel lets developers start on a shared USSD short code for testing and move to a dedicated code for production, so you can dial your menu from ordinary handsets before launch. Arkesel’s USSD service runs on MTN, Telecel and AirtelTigo in Ghana, so test with a SIM on each network.

On each network, walk every menu path, including wrong inputs and the back option. For screen length and wording, our USSD menu design best practices cover what to check. Then check the replies your server logged. Arkesel’s documentation requires your response body to contain all of the documented response elements: every request in one session carries the same sessionID, and your response must return sessionID, userID and msisdn exactly as received, with a mandatory message field.

The shared test code is for these manual checks only. Point load tests at your own endpoint or a staging copy of it, and never at the shared test code, Arkesel’s gateway or the mobile networks.

Which tools can you use to load test a USSD application?

Because the callback is ordinary JSON sent by HTTP POST, general web testing tools can exercise it. Choose one tool for each job: a load generator, a way to replay requests, a fake-data library and monitoring.

ToolJobHow it fits a USSD callbackWhat it reports
Grafana k6Load generatorAn open-source performance testing tool designed for running high-load tests such as spike, stress and soak tests, which matches the busy-day and promotion-launch tests belowAn end-of-test summary that includes the median, p(90) and p(95) by default (p95 is the response time that 95% of requests come in under; p90 and p99 are the same for 90% and 99%); thresholds give pass or fail results
Apache JMeterLoad generatorOpen-source Java software designed to load test functional behaviour and measure performance, and it can simulate heavy load on a serverMeasurements of your server’s performance under that load
LocustLoad generatorTests are written in regular Python code, which suits teams whose backend is already in PythonThroughput, response times and errors, viewable in real time
Postman Collection RunnerRequest replay and light performance runsSends a collection’s requests in the order you choose and can pass data between them, so a saved menu path replays step by stepTest results for each request; performance runs show virtual users, requests per second, average response time and error rate
curlSingle-request replayPosts data exactly as specified, with extra headers, so you can send one JSON request to your own endpointYour server’s reply to that request
Faker (Python) and Faker.jsFake dataGenerate large volumes of fake users and records for local and staging databasesNot a measurement tool
Prometheus with GrafanaServer monitoringCollects your server’s metrics while the test runs, so you can line them up against the loadMetrics stored as time series, which Grafana can chart

If you already use Postman, the Collection Runner can be used to test API performance with the same requests and environments used for functional tests, which makes it a practical first performance run. For the average-load and spike tests below, use a load generator, and choose by how your team works: Locust tests are written in Python, JMeter is a Java application, and k6 is designed for high-load tests such as spikes.

Whichever tool you pick, make the replayed requests match what Arkesel sends. Arkesel opens a USSD session by sending a request with newSession set to true; your response sets continueSession to true to keep the session open or false to close it. A replayed menu path should follow the same pattern, with one sessionID across all of its steps.

USSD load testing tools by job, around your local or staging endpoint: a load generator such as k6, Apache JMeter or Locust; request replay with Postman Collection Runner or curl; fake data from Faker (Python) or Faker.js; and server monitoring with Prometheus and Grafana

How do you test a USSD application locally with realistic data?

Run your first tests on your own machine, against a database filled with realistic fake data. A near-empty database can make lookups look faster than they will be once months of customers, sessions and transactions have built up, so test at the size you expect to reach rather than the size you have today. Work in this order:

  1. Decide the load you are planning for. Grafana’s k6 guide on average-load testing says the expected load should come from production analytics, or from business estimates when those tools are not available. For a new service, that means your estimate of how many customers will dial at your busiest moment. Size every later test from that peak.
  2. On a local or staging copy only, seed the database with fake data. Never do this on production. Before you clear or reseed any database, take a copy of it, then load the fake data. Use a library such as Faker or Faker.js to generate users, accounts, past sessions and transactions at the volume you expect after several months. Use generated phone numbers only, never real customer numbers.
  3. Vary the request data. Each Arkesel USSD request carries the user’s mobile number (msisdn), what the user typed (userData), the mobile network the request came from (network) and a newSession flag. Spread test requests across many fake numbers and all three networks, so the test reflects many customers rather than one number dialling repeatedly.
  4. Check one request, start monitoring, then run a smoke test. Send one JSON request to your local endpoint with curl and confirm the reply carries the required fields. Start collecting your server’s metrics, for example with Prometheus, before any load begins, so every run has numbers to compare. A smoke test applies minimal load to verify the system works and to gather baseline performance values. Note the response times you see. This baseline is where you set your own reply-time limit.
  5. Ramp the load slowly. The same k6 guide advises first-time load testers to start small or ramp up slowly, warning that applications and staging environments can crash quickly under a load test. Raise the load in steps towards your expected peak and watch the measures described below at each step.

Local results expose problems in your own code and queries. They say much less about your production server settings, which is what staging is for.

Why test in a staging environment before going live?

Your local machine differs from production in hardware, settings and network setup. Our reasoning is that a staging copy that mirrors production reveals the limits that sit in configuration, such as database connection limits or web server worker settings, because they only appear when the configuration matches.

Set staging up to match production as closely as you can:

  • the same server size and operating system
  • the same web server and database settings, including connection limits
  • the same network path in front of the application, such as a load balancer or proxy
  • the same volume of seeded fake data you used locally, loaded the same way: take a copy first, and only on the staging database

Then repeat the sequence. Grafana’s k6 testing guide recommends starting with smoke tests before moving to higher loads and longer durations, and distinguishes average-load tests (expected normal conditions) from spike tests (sudden, short, massive increases in activity). An average-load test shows how you handle a normal busy day. A spike test shows what happens in the first minutes of a promotion or on salary-day morning.

Order of USSD application testing: real handsets on MTN, Telecel and AirtelTigo using the shared test code, then your own machine with realistic fake data and a smoke-test baseline, then a staging server set up like production, then the go-live decision at your expected peak. Point load tests only at your own endpoint or a staging copy, never at the shared test code, Arkesel's gateway or the mobile networks.

What should you monitor during a USSD load test?

Watch the four golden signals that Google’s Site Reliability Engineering book names for a user-facing system: latency, traffic, errors and saturation. For a USSD service, they translate into these measures.

What to watchWhy it matters for USSDWhat a not-ready result looks like
Response time per request, including p95 and p99Every reply uses part of the session window, and one customer passes through several replies in a sessionThe slowest replies keep climbing as load rises, or exceed the limit you set from your baseline
Errors, including success replies with the wrong contentA reply that returns a 200 status but leaves out a required field, or returns a different sessionID, still fails the customerErrors appear or grow as load rises
TimeoutsA request your load tool gave up on is a screen the customer never receivedAny timeouts at or below your expected peak
TrafficConfirms the test actually reached the load you plannedThe test cannot reach your planned request rate
Saturation: CPU, memory, database connectionsShows which resource will run out firstA resource sits at its limit while load is still rising

Watch the tail as well as the average. Google’s SRE book offers an illustration rather than a measurement: a web service averaging 100 ms at 1,000 requests per second might easily see 1% of requests take 5 seconds. On USSD, each customer makes several requests per session, so a small share of slow replies can touch a larger share of customers. The book also says rising latency is often a leading indicator of saturation, and that the 99th percentile response time over a short window can give a very early signal of it.

The same book counts as errors requests that fail explicitly, such as HTTP 500s, and requests that fail implicitly, such as an HTTP 200 response with the wrong content, so have your test check each reply body for the required fields. It also defines saturation as how full the service is in its most constrained resources, so watch the resources yours depends on, such as CPU, memory and database connections.

If you use k6, its end-of-test summary shows trend statistics including the median, p(90) and p(95) by default, set by the summaryTrendStats option, which you can change to add p(99). k6 thresholds are pass/fail criteria on test metrics such as error rate or response time, so set them from your own baseline and a run that misses them finishes with a failed status.

What result means a USSD application is not ready to go live?

Treat any of these at or below your expected peak as a reason to hold the launch:

  • the p95 or p99 response time keeps climbing as load increases
  • errors or timeouts appear, including 200 replies that are missing required fields
  • CPU, memory or database connections sit at their limit
  • replies stop coming back well inside the 150 to 180 second window, or go past the limit you set from your baseline

When you see one, find and fix the cause, such as a slow query, a connection limit or an undersized server, then rerun the same test so you compare like with like.

How to test a USSD application before going live: a checklist

  1. Every menu path works on handsets on MTN, Telecel and AirtelTigo using the shared test code, and every reply carries the required fields.
  2. Your expected peak comes from your own analytics or business estimates.
  3. Locally, you took a copy of the database before seeding, loaded realistic fake data, started monitoring, recorded a smoke-test baseline and ramped the load slowly.
  4. Staging matches production, holds the same data volume and has passed smoke, average-load and spike tests.
  5. None of the not-ready signs above appeared at your expected peak.

When the list is clear, you are ready to move from the shared test code to a dedicated code for your production service. Dedicated USSD codes in Ghana are assigned by the National Communications Authority (NCA), so allow time for that step; our guide to getting a USSD shortcode for your business in Ghana walks through it. Talk to Arkesel about a dedicated code, or read the Arkesel developer documentation for the full request and response format.

Scroll to Top