The sequence, start to finish
We say the build is the easy part and that production is the whole job. That is a claim against our own sales interest, so it is only worth anything if we show what we do rather than assert that we do it.
Every piece of work moves through the same sequence, in the same order, whether it is a two-week process fix or a connected system. The order is not a preference. Each step exists because skipping it costs more later than doing it costs now.
- Understand what actually happens. Not the process as documented, but the process as run, including the part where somebody re-keys it on a Friday.
- Decide the boundaries before anything is built. What data the system may reach, what it may retain, who sees an output. These are structural; made late they mean building twice.
- Build the smallest thing that proves it works, against real data rather than a sample, and put it in front of the people who will use it while it is still cheap to change.
- Review it against a written standard, by somebody who did not write it.
- Run it in parallel with the old way until it is boring. The point at which nobody mentions it is the point it has worked.
- Hand over the decisions, not just the code, so somebody who was not there can change it in a year.
Every gate, and what it blocks
A gate is a point where work stops until somebody who is not the author agrees it may continue. We run these on our own builds before we run them on anyone's.
Architecture
Anything touching a database schema, an API contract or how services talk to each other is reviewed before it is written, not after. The cheapest moment to change a structural decision is before there is anything built on it.
Standards
Naming, secrets, and the rules that stop a codebase becoming unreadable by the second person. Blocks on a hardcoded credential every time, without discussion.
Security
Anything touching credentials, authentication, external services or somebody else's data. It is a gate rather than a review step, which means it cannot be passed with a promise to look at it afterwards.
Testing
Tests ship in the same change as the code they cover. A test written later is a test written to pass.
Deployment
One role holds it and it is not delegable. That sounds bureaucratic for a two-person firm and it is the opposite: it is what stops a change reaching production because both of us assumed the other had checked.
What we do when a check fails
The work stops. That is the entire answer, and it needs saying because the alternative, noting the failure and proceeding, is what most processes quietly do under deadline.
A gate that can be waived when it is inconvenient is not a gate; it is a log entry. So the failure gets fixed, or the scope changes, or the date moves. We would rather tell you a date has moved than hand over something that did not pass its own check.
A process that never blocks anything is not working
A process that never blocks anything is not a process that is working well. It is a process nobody is running. If we ever tell you every check passed first time on a substantial build, ask which checks.
What is still running after we step back
The test of a build is not the day it launches. It is whether it still does the right thing six months later, when the person who wrote it has stopped looking at it and nobody remembers why a particular check is there.
So the handover is not a document. It is the set of things that keep working when nobody is watching. On our own builds that has meant:
- A suppression list the sender checks before every single message leaves, so a do-not-contact instruction cannot be undone by a later import.
- A review queue nothing bypasses. No override, no exception for a draft that looks fine, no quiet path around it for a hurry.
- A screen that makes adoption failure visible instead of assumed: every customer account flagged as never opened, invited and waiting, or silent for thirty days.
- A read-only preview, so staff can see exactly what a customer sees without being able to change anything while they look.
- Audit tables for administrative actions and for every export of data out of the system.
- An import that preserves the links already made rather than rebuilding them, because a monthly routine that quietly discards last month's corrections is worse than no routine.
- A health check every fifteen minutes, added after an outage that ran for nine days before anyone noticed, because the layer in front of it kept returning a normal response the whole time.
The one we have not finished, named on purpose
An alert for when a sync stops. The flag that records a failed run is written every time and nothing reads it, which means the information exists and no one is told. We would rather say that here than let you assume a monitoring story we cannot stand behind. It is the difference between a system that is monitored and one that merely could be.
Why the decisions get written down
Code says what a system does. It does not say what else was considered, what was rejected, or why. A year later that missing half is what makes a small change expensive. Somebody has to re-derive a decision from scratch, and usually re-makes the mistake it was avoiding.
So each significant decision is recorded with its reasoning and its alternatives, including the ones we later reversed. The reversals are the most useful entries, because they are the only ones that say what we got wrong.
This is also what makes a system yours rather than ours. A business that holds the decisions can change suppliers. A business that holds only the code is renting from whoever built it, and it usually does not find out until it wants to leave.