When you buy custom software, you are buying a promise that it will keep working — on the day it launches, and every day after, as people lean on it harder than the demo ever did. Most buyers cannot inspect the code, so they judge quality by the polish of a sales meeting. That is the wrong instrument. Quality is not a feeling you get in a demo; it is a set of habits you can ask about directly, and the answers tell you far more than a slick presentation ever will.
Quality is built in, not tested in at the end
The most expensive misconception in software is that quality is a phase near the end — a week of testing before launch that catches the mistakes. It does not work that way. By the time software is finished, a bad decision made in the first month is woven through everything built on top of it, and no amount of end-stage testing pulls it back out cheaply. Testing at the end finds surface defects; it cannot repair a foundation.
Quality that lasts is decided continuously, in small choices made every day: how a feature is scoped before it is written, whether the person who wrote a piece of code had a second pair of eyes on it, whether the system checks itself automatically before anything reaches you. A team that treats quality as a final gate is telling you they expect to find problems late, when they are hardest to fix. A team that builds it in expects to find problems early, when they are cheap. Ask which one you are hiring.
The layers a buyer should know
There is no single thing called "testing." There are layers, and each catches a different kind of mistake. Automated tests are code that checks the software the same way every time, in seconds, so that a change made today does not silently break something that worked yesterday. Code review means no important change ships on one person's judgement alone — a second engineer reads it before it lands. Continuous integration, usually shortened to CI, is the robot that runs all of those checks automatically every time code changes, so nobody has to remember to.
On top of that sit two human layers. QA — quality assurance — is deliberate testing by someone whose job is to try to break the software the way a confused or hurried real user eventually will. And UAT, user acceptance testing, is where you and your own people confirm that the software does what your business actually needs, in the language of your business rather than the developer's. You do not need to understand how each layer works internally. You need to know that a serious build has all of them, and to notice when one is quietly missing.
What good looks like without the jargon
You can recognise quality from the outside if you know what to watch for. Good software fails clearly, not mysteriously: when something goes wrong, it tells you what and why, rather than freezing or losing your work. It behaves the same on the tenth try as the first. It handles the awkward cases — the empty form, the duplicate entry, the customer with an apostrophe in their name — instead of only the tidy happy path a demo shows.
There is an internal signal too, and you are allowed to ask about it. When a small change is requested, how nervous is the team? In a healthy system, a small change is a small change. In a fragile one, every small change carries the risk of breaking something unrelated, and you feel it in the hesitation and the padded estimates. That fear is the clearest symptom of quality that was never built in — and it is the tax you will pay on every future change for as long as you own the software.
One more outward sign is worth naming: how the software behaves under conditions nobody gently walked it through. Quality shows when many people use it at once, when a report runs against years of data, when the network is slow and a request half-completes. Poor software is written for the demo — one user, clean data, a fast connection — and it cracks the moment reality is messier than that. Good software assumes the mess, because the people who built it have watched real users find every sharp edge, and they rounded those edges before you ever met them.
Why skipping tests feels cheaper — and costs more
Cutting testing is the easiest saving to sell, because the cost of skipping it is invisible at the moment you skip it. You ship sooner, you spend less, and for a while nothing bad happens. The bill arrives later, and it arrives with interest. A defect caught by an automated test costs minutes. The same defect caught by your customer costs a frantic phone call, an emergency fix, the trust of the person it hit, and the credibility of everyone who promised the software worked.
There is a compounding effect that makes it worse. Without tests, every new feature is built on ground nobody is sure of, so each change is slower and riskier than the last. The team spends more and more of its time firefighting and less building, until the software feels stuck — expensive to touch and frightening to change. The money you saved on testing did not disappear; it moved into a line item called "why does everything take so long now," and it keeps growing. Testing is not a cost centre. It is what keeps the cost of change flat instead of rising.
It helps to picture the two curves. With testing in place, the cost of making a change stays roughly flat for years — the hundredth change is about as safe and as quick as the tenth. Without it, that curve bends upward: each change is a little riskier and a little slower than the last, because nobody can be sure what it might disturb. The two curves start close together, which is why skipping tests looks free at launch, and they diverge relentlessly, which is why the same team that shipped fast in month one can barely move by year two.
How to tell if a partner takes quality seriously
You can assess a partner's real posture on quality in a single conversation, without a word of code. Ask them to walk you through what happens between an engineer finishing a feature and that feature reaching your users. A serious answer describes several steps — review, automated checks, a QA pass, a staging environment that mirrors production — and it sounds routine, because for them it is. A weak answer is some version of "we test it before release," which usually means one person clicking through it once.
Ask what happens when something breaks in production at an inconvenient hour. A serious team can tell you how they would find out, who responds, and how they stop the same thing recurring — not just how they patch it. Ask how they know the software still works after a change: if the honest answer is "we check the parts we think we touched," you have learned that regressions are your risk, not theirs. And watch how they talk about their own mistakes. A partner who can describe a bug they shipped and what they changed afterwards is telling you they take quality as a practice. One who has never shipped a bug is telling you they are not being straight with you.
Your side of the bargain
Quality is not something you can fully outsource, because a large share of defects are not broken code — they are software that works exactly as specified, where the specification was wrong or unclear. Your part is to make "done" mean something concrete before work starts. That is what acceptance criteria are: a plain description of what a feature must do to be considered finished, written well enough that both sides would agree, looking at the result, whether it passed. Vague criteria are how two reasonable people end up in an argument about whether the thing they both looked at is correct.
The other half of your role is user acceptance testing, and it deserves real time from real users. UAT is not a formality to rush through the day before launch; it is your last and best chance to catch the gap between what you asked for and what you needed. The people who do the work every day will find awkwardness a specification never captured. If you treat UAT as a box to tick, you are choosing to discover those gaps in production instead — in front of customers, at the worst possible cost.
Bugs will happen — the question is how fast they are caught
No honest engineer will promise you software without bugs, and you should distrust anyone who does. All meaningful software has defects; the difference between a well-run system and a troubled one is not the absence of bugs but the speed and grace with which they are caught and contained. In a healthy system, most defects are found by tests or QA before you ever see them, the few that escape are noticed by monitoring before customers complain, and a fix ships calmly rather than in a panic.
That is the real thing to buy: not perfection, but a short distance between a mistake being made and a mistake being corrected. Everything in this article — building quality in, the layers of testing, clear acceptance criteria, a partner who takes it seriously — exists to keep that distance short. When it is short, bugs are a nuisance. When it is long, they are a recurring crisis, and no launch-day demo will have warned you which one you bought.
There is a practical way to check this distance before you commit. Ask a prospective partner how they would learn that a defect had reached production, and how long a typical fix takes from the moment it is noticed to the moment it is live. A team that has built quality in answers with a process; a team that has not answers with a promise to be careful. The difference is the whole thing you are buying, and it is measurable in hours, not adjectives.