Preparing a Technical Specification Before You Commission a Build
Most unpleasant software projects are not caused by difficult technology. They are caused by a requirement that was understood differently by the two parties and discovered late.
A specification is not a contract and it is not a proposal. It is the record of what has been agreed about a system before anyone builds it, and its value depends almost entirely on how much of it has been decided rather than assumed. The sections that cause trouble later are rarely the technical ones. They are the ones nobody wrote down, because everybody in the room seemed to know the answer already.
Describe the users, not the features
“Users can reset their password” describes a feature. “A customer who has locked themselves out can regain access without contacting support” describes a need, and it is far easier to design, build and test against. Feature lists built this way also tend to be shorter than the ones they replace, because several features often turn out to be one need expressed three times.

Name the person and the moment
A need only becomes buildable when it identifies who is doing it, what they have already tried, and what a good outcome looks like from where they stand. Consider the reset example again. The moment that matters is somebody who has tried twice, is holding a train ticket, and is convinced the site has lost their account. Written that way, the specification starts answering questions it would otherwise have skipped: can the link be requested twice, does the old one stop working, what happens to an order placed in the meantime.
Trace a journey rather than listing screens
Pick one important path and follow it from arrival to confirmation, including every point at which it can go wrong. A specification organised as a list of screens leaves the joins between them to whoever is building, and the joins are where the work is. Every request also creates a second person downstream: a self-service form reduces support contacts, an approval queue moves them into a queue somebody must work through. That person is often the real motivation for the project, and their tolerance is often what decides the design.
Write down what is explicitly out of scope
The most useful section of a specification is the exclusions. It prevents the slow accumulation of “while we’re in there” additions, and it protects both the timeline and the relationship when a good idea arrives mid-build. Exclusions are also the honest part of the document: they are the place where you admit what is not being solved, which is what makes everything else in it believable.
The categories worth naming
- Devices, browsers and screen sizes that will not be supported, stated as a list rather than an aspiration.
- Languages and locales, including date formats, currency handling and right-to-left layout if it is likely to be needed later.
- Administration: how many roles, who gets one, and what they are permitted to see.
- Existing data: whether anything is migrated, cleaned or reconciled, and if so by whom.
- Content and assets: who writes the copy and approves it before publication.
- Life after launch: training, documentation, and how much support is included in the price.
Two things make the section work. Name where each excluded idea will live instead, so it lands in a plan rather than an argument. And expect a supplier to push back on some exclusions, treating that as useful information, because an exclusion nobody thinks is necessary is often one nobody has examined.
Name the integrations precisely
“Integrates with our CRM” is not a specification. Which system, which endpoints, in which direction, how often, and what happens when it fails are all questions that need answers before a price is meaningful. The same applies to payment providers, accounting packages, messaging services and anything that sends email. Ask the provider for their rate limits and their sandbox access before the estimate, not after.

Questions worth putting to any third party
- How authentication works, and whether access is delegated or a set of credentials is stored and looked after by your system.
- Whether sandbox access exists, whether test data behaves differently from live data, and who pays for the service in each environment.
- What the rate limits are and what happens when they are exceeded: queued, retried, or rejected.
- How failures are reported, and whether a failure is loud or silent.
- What happens to the connection if the account is cancelled, the subscription lapses, or the person holding the login leaves.
Then say which way the data moves: push or pull, who initiates, how often, and what happens to a record that arrives incomplete. Where two systems hold the same information, name which one is authoritative rather than leaving both to win. This is where a system integration either holds together or quietly becomes a source of contradiction, and it is far easier to settle before anything is built. State plainly which system owns each credential and in whose name the account is registered.
Say what happens when things go wrong
For every external dependency, decide what the system does when that dependency is unavailable, slow or returning nonsense. Does the order fail, or is it queued? Does the screen show an error, or does it silently show stale data? These are the decisions that are impossible to make during an incident and trivial to make on paper.

Write failure behaviour next to the happy path
Failure modes listed in a separate section get forgotten, because nobody reads them while working on the feature they were actually asked for. Put them next to the behaviour they belong to. A payment form needs to say what happens on a double submission, a partial write, a timeout after the money has moved, and a provider that accepts a request and then declines it quietly.
Some cases get discovered late: a queue that grows for three days while an external service is down; a search that returns nothing and looks identical to a broken search.
Decide who finds out
An alert nobody reads is not monitoring. Agree what gets logged, how long the logs are kept, what threshold should reach a person rather than a mailbox, and who is allowed to act on it overnight. Naming that person is uncomfortable in a document people will reread later, and it is the difference between a decision and a hope. None of this is defensive pessimism: it is a paragraph now, or a redesign during an incident when the options are all bad.
Decide who owns the data, and where it lives
Before anyone writes code, settle which system is the record of truth for each piece of data, and where a copy is allowed to live. Duplicated data with no stated owner is the single most common cause of a system that disagrees with itself, and it is much harder to unpick after launch than to prevent in the specification.
Personal data, retention and exit
What is collected, why, who inside the organisation can see it, how long it is kept, what happens when a person asks for a copy or for deletion, and what happens to data sitting in a backup. Write the answers down even where they feel obvious, because obvious is where the disagreement is waiting.
Then ask what a full export looks like, in what format, how long it takes and who may run it. A system holding the only copy of something and unable to produce it in a readable form has taken ownership of it. That question also determines how confidently anyone can commit to a future change of supplier.
Agree how completion is judged
Define the acceptance criteria before the work starts, in terms someone outside the project can check. Without them, “done” is a matter of opinion, and the argument appears at the least convenient possible moment. Acceptance criteria written as “a customer can complete a return without contacting support” survive contact with reality better than a list of screens.

Write criteria a stranger could check
A useful test is whether somebody who has never spoken to the people who wrote the document could run the criterion and reach the same conclusion. “The search is fast” fails. “Searching a catalogue of the current size returns results in under a second on the connection the offices actually have” does not, even though it is longer. Quality assurance work is only meaningful against criteria written in this form, which is why they belong in the document rather than in a conversation at the end.
Blocked, producing a wrong result, unusable on a supported device, and cosmetic are four different things and should not carry the same weight. Settling that in advance stops a list of small annoyances becoming a dispute about acceptance. Keep a dated list of known limitations as the build progresses: a limitation recorded in week four is a fact, and the same limitation presented as new in week twelve is an argument. Every criterion should also say where it is being verified, because a behaviour that passes on a developer’s machine and fails on a staging copy holding realistic content has not been met.
Who writes it
Ideally the people who know the business, with a technical reviewer involved early rather than at the end. It is much harder to fix after a supplier has quoted against it. If that is not possible, the useful alternative is a set of written questions from the development team, answered once, in order.

Name an owner, separately from a signatory
Several people usually hold the knowledge and none of them owns the document. Name one person accountable for the specification as a document, distinct from whoever signs it off commercially. The distinction matters, because a document owned by the signatory tends to lose its inconvenient sections first.
Where nobody will write it, the fallback that works is a structured list of questions sent round once, answered once, in order, and assembled by somebody whose actual job is assembling it. That looks slower than sitting down to write and finishes considerably faster than a supplier inferring the answers and pricing the guess. If the project is unclear enough to need that, an appraisal or discovery engagement is usually worth the money, because the questions then get asked in a room rather than in writing afterwards. Either way, bring in a technical reviewer before the document is finished rather than after it has been quoted against: findings at that stage are close to free, while findings after a supplier has priced the work become a conversation about a different number.
Keep it short enough to read
A specification nobody finishes reading has no effect. Ten pages of genuinely necessary detail beats forty pages that include everything that might matter. Where something is not yet known, say so and say when it will be decided, rather than filling the gap with a plausible-sounding assumption. An assumption written into a specification will be built.
An order that works
Purpose and who it is for; the journeys; the data and who owns it; the integrations; the exclusions; the acceptance criteria; the open questions; and a change log. The same order every time, so a reader who has read last month’s specification knows where to look. Use it consistently across projects and the format stops needing explaining.
Give open questions their own section rather than hiding a guess inside a paragraph of confident prose. A document listing three unresolved questions, with an owner and a date against each, is more useful than one that pretends. Then put a version number and a date on it and note what changed at the end, so that when a requirement arrives verbally in week six the question of what it affected is answerable in seconds instead of by argument. This is part of what how a project is run should cover, because a document without a version cannot carry a change.
Before it goes to anyone else
Read it aloud to somebody else. Anything you stumble over is ambiguous, and ambiguity is exactly what gets built two different ways by two careful people. After that, a short check covers most of the remaining risk:

- Every requirement can be traced back to a need stated earlier in the document.
- Every exclusion has a reason attached, not just a decision.
- Every external system is named, with the questions about it answered.
- Every journey describes what happens when a step fails.
- Every unknown appears in the open questions section with an owner and a date.
- No single word is doing two jobs in the same paragraph.
Give it next to somebody who was not in the original conversation. The questions they ask are the document’s real gaps, because they are the questions a developer will ask in week two. Expect to write it twice: the first version is a list of what people want, and the difference between that version and the second is an unusually honest record of what the project turned out to be. Once it exists, it becomes the reference against which a custom software build is described, quoted, built and finally accepted. That is the document SmartEdge IT Solutions asks for before quoting, because it is what stops a build being priced against a guess.
