Graphic: Labwor Technologies
The failure modes are rarely technical
When a software project fails here, the post-mortem almost never lands on a hard engineering problem. Nobody ran out of algorithms. What went wrong was a generator with no fuel, a finance officer waiting for the next quarter, a scope that grew quietly after the deposit cleared, or a spreadsheet that existed on exactly one laptop and that laptop went to a funeral in Mbale.
I have built systems for a savings cooperative, an engineering firm, a professional institution’s elections, a driving school and a large church camp, and I have deployed clinical software for facilities in Uganda, Burundi and Botswana. The pattern holds. The interesting risk sits outside the repository, which means the skills that protect a project are frequently not programming skills at all.
This is worth saying plainly because the advice available to Ugandan developers is mostly imported. It assumes reliable electricity, reliable bandwidth, card payments, an in-house product owner and a client who pays on net thirty. Strip those assumptions out and a good deal of standard practice stops being neutral and starts being a source of risk.
I do not think this makes Ugandan projects harder than projects anywhere else. It makes them differently hard, and the difference is that most of the difficulty is visible in advance if you are willing to look for it. A power failure is not a surprise. A ministry’s quarter-end is published. The cousin who knows computers has been in that family for years. Almost every failure I have watched was foreseeable, which is a more useful and more uncomfortable conclusion than blaming the environment.
Power and connectivity, which are not the same problem
Most software is written by people who have never watched their own application die mid-transaction. Here you learn early to distrust the idea of a machine that is simply on.
The consequence is not only downtime, it is partial writes and half-finished states. A registration submitted at the moment the lights go is a row that may or may not exist. If your design assumes the user will simply try again you will get duplicates, and with no way to detect duplicates you have created a data problem that surfaces months later in an audit. The fixes are dull and cheap: make writes idempotent so submitting twice does not create two members, keep drafts locally as the user types rather than only on submit, and treat a session that ends without warning as the normal case rather than the exception.
Connectivity is a separate matter and the numbers on it are counterintuitive. The International Telecommunication Union published its report on the state of digital development in the Africa region in April 2025. By 2024, mobile broadband covered 86 per cent of Africa’s population, yet only 38 per cent of the population used the internet, against a global average of 68 per cent. Coverage is not the binding constraint. Something else is.
Cost is a large part of it. The same report puts the median price of two gigabytes of mobile broadband a month at 4.2 per cent of gross national income per capita in 2024, the highest of any region and well above the UN Broadband Commission’s target of two per cent. The internal gap is worse still: internet use reached 57 per cent of urban populations but only 23 per cent of rural ones, the widest such divide the ITU found anywhere.
Africa in 2024. Coverage is not the binding constraint. Source: ITU, April 2025.
Uganda sits at the difficult end of this. In the ITU’s country-by-country comparison of individuals using the internet, drawn on 2023 figures, Uganda appears among the three lowest in the region. The Uganda Communications Commission counted around 18.5 million internet subscriptions as of December 2025, in a country of well over forty million people.
If your product needs a stable connection to be useful, you have quietly restricted it to towns. That may be a defensible business decision. It should be made deliberately rather than inherited from a framework default.
Payment and procurement cycles
This is the risk that kills small firms rather than projects. An NGO cannot pay you outside its fiscal year. A government entity needs a purchase order routed through a procurement and disposal unit that answers to a calendar you cannot see. A private company will pay a deposit quickly and then discover that the balance sits behind a director who is travelling.
None of that is bad faith. It is simply how institutional money moves, and it moves on its own schedule regardless of how well you are performing. The mistake is building a delivery plan that assumes money arrives when work is done. Stage payments against things the client can see working, keep the stages small enough that no single delay stops you eating, and put the payment trigger in writing immediately next to the deliverable it belongs to, in the same sentence if possible.
On the collection side, the rails here are strong and improving. The Bank of Uganda reported in 2025 that electronic money transaction values grew 28.6 per cent, from UGX 253.7 trillion in the twelve months to June 2024 to UGX 326.3 trillion in the year to June 2025, with volumes rising from 7 billion to 8.4 billion transactions and the agent network expanding from 775,294 to 1,016,914. When I built a fashion e-commerce app for a store in Gulu, mobile money was not an alternative tender bolted on beside cards. It was the payment method, and the delivery flow was designed around it. Building card-first and adding mobile money later is a way of shipping a product that most of your market cannot buy.

A market stall in Uganda, where the mobile money rails actually run. Photo: Andrew Itaga, Unsplash.
Scope drift, and the cousin who knows computers
Scope does not usually grow through greed. It grows through relief. The client sees the first working thing, realises software can be shaped, and starts imagining. That imagination is genuinely valuable, and killing it is bad for the product. Left entirely unmanaged, it is also how a six-week site becomes a five-month site at the original price.
The defence is a written scope specific enough to be checked. Not a list of services, a list of behaviours: what a user can do, on which page, and what happens afterwards. When a new request arrives it goes onto a second list with a price and a date attached, and the client chooses. Most clients accept this the moment they understand they are choosing rather than being refused. The ones who will not accept it were always going to be your difficult project.
Then there is the cousin who knows computers. Every project meets him eventually. He is real, often genuinely capable, and he holds the client’s trust in a way you have not yet earned. He will look at your work and say it should have been WordPress, or that the hosting is overpriced, or that he could have done it for a third of the fee.
Fighting him is a losing move because you are arguing against a relationship, not an argument. What works is making him a participant. Ask his opinion in front of the client. Give him read access. Explain in plain terms, without condescension, why a thing is built the way it is. Most of the time he becomes an ally, because what he actually wants is to be treated as competent, which he frequently is. And on the occasions when he is wrong in a way that matters, you want him to have been in the room when the decision was explained, so that the client remembers who said what.
Data that lives on one laptop
I have lost count of the organisations whose real institutional memory is a single spreadsheet on a single machine, backed up occasionally to a flash drive that has also visited three internet cafes.
This is probably the most common data architecture in the country and it fails in two directions. It fails loudly when the laptop fails. It also fails quietly, every single day, because only one person can hold the truth at a time, so decisions get made from stale copies that were emailed around last month and have been edited independently since.
Moving an organisation off that pattern is not primarily a technical task. It is a trust task. The custodian of that spreadsheet has real authority derived from holding it, and a new system takes that away. You have to give them something better than what they had, including a working export, or they will keep the laptop version running in parallel and you will have two sources of truth instead of one, which is worse than where you started.
The practical route in is to migrate the spreadsheet rather than replace it. Import their columns, including the odd ones nobody can explain, and show them their own data inside the new system on the first day. Arguing about data modelling before that point is a losing conversation. Once they can see their records intact, the discussion shifts from whether to move to what to fix, and that is a discussion they will lead.
What de-risking looks like in practice
Everything above points at the same handful of habits, and I now treat them as defaults rather than as options.
- Build offline-first wherever the work happens away from towns. Scholaris, the school reporting system I am building, holds a term’s marks on the device and syncs when it can, because a head teacher in a rural school should not need bars on their phone to finish a report card.
- Put mobile money in the first slice, not the last.
- Write scope as behaviours, and price changes rather than refusing them.
- Stage payments against visible, working slices the client can operate alone.
- Budget real time for handover training, and treat it as a deliverable.
That last one deserves more than a line. When I customised and deployed Bahmni for a clinic in Kampala, and when I trained teams on OpenMRS configuration for clients in Botswana and the United States, the training was not a courtesy at the end of the engagement. It was the part that decided whether the system survived my departure. A system nobody has been taught to operate is a system that quietly reverts to paper within a quarter, and the client will remember that as your failure, correctly.
Each failure mode, and the default that answers it.
The engineering is the part I can control from a desk in Kampala. Everything else, the fuel in the generator, the quarter-end at the ministry, the cousin, the laptop holding the only copy, is the actual project. I used to treat those as interruptions to the work. They are the work, and the sooner a delivery plan admits it, the fewer apologies it has to make later.
Sources and further reading
Frequently asked questions
Why do software projects fail in Uganda?
They rarely fail on the engineering. The common causes are a power cut mid-transaction, a client's payment stuck behind an institutional budget cycle, scope that quietly grew after the deposit cleared, or an organisation's real records living on one laptop with no backup. Almost every failure is foreseeable if a team is willing to look for it outside the code itself.
Should a software project for an NGO or institution in Uganda be built offline-first?
Usually, yes, if the work happens away from towns. Mobile broadband reaches most of the population, but actual internet use lags well behind it, and the Uganda Communications Commission counted only around 18.5 million internet subscriptions in a country of well over forty million people. A product that assumes a stable connection has quietly restricted itself to towns, which may be defensible, but should be a deliberate decision rather than an inherited default.
Why should mobile money be built into a Ugandan project from the start rather than added later?
Because it is already how most people here pay. Electronic money transaction values in Uganda grew 28.6 percent in a single year, according to Bank of Uganda data, and a project that treats mobile money as an add-on rather than the default payment method ends up shipping something most of its market cannot actually use. It belongs in the first slice of work, not the last.