Threat modelling before the first line of code
Most breaches trace back to a design decision, not a coding mistake. Here is the two-hour session we run at the start of every build — and the template we use.
AI
Demos are easy. Evaluation harnesses, grounding, injection defence and cost ceilings are what separate a prototype from a product.
Building an impressive LLM demo takes an afternoon. Building one that still behaves three months later, under adversarial users, with a cost line that finance will sign off on, is a different discipline entirely. Here is what we put around every AI feature before we let it near production.
The first artefact on any AI project we run is not a prompt. It is a spreadsheet of one hundred or so real inputs with the outputs we would accept, assembled with the people who will actually use the feature. Until that exists, nobody can tell whether a prompt change is an improvement or a regression — including you.
That set then runs in CI on every prompt or model change, scoring exact matches where the task allows it and using a model-graded rubric where it does not. When a change drops the score, the pull request fails. It is unglamorous and it is the difference between engineering and vibes.
Retrieval-augmented generation is now standard, but the implementation details decide whether it works. Three things matter more than the vector database you choose:
This is where our security practice earns its keep. Any text that reaches the model from outside your trust boundary — user messages, retrieved documents, scraped pages, email bodies, PDF contents — is untrusted input, and it can carry instructions.
The defences that hold up in our testing:
Prompt injection is not solved. Design as though the model will eventually follow a malicious instruction, and make sure that when it does, nothing important happens.
Set the numbers before you build, not after finance asks. For each feature we fix a p95 latency target and a maximum cost per request, then design to fit. That usually means routing simple cases to a smaller, faster model and reserving the large one for genuinely hard inputs, caching aggressively on stable prefixes, and streaming responses so perceived latency stays low even when total latency is not.
On our last three deployments this approach cut per-request cost by 60–80% against a naive single-model implementation, with no measurable quality loss on the evaluation set.
Every AI feature we deploy has a feature flag, a fallback path that works without the model, and a dashboard showing volume, latency, cost, refusal rate and user-reported failures. When a model provider has a bad hour — and they do — you want the feature to degrade rather than take the product down with it.
Most of the work in a production AI feature is not the AI. It is the evaluation harness, the retrieval quality, the security boundary and the operational instrumentation. Teams that build those first ship features that last. Teams that start with the prompt ship demos.
Keep reading
Most breaches trace back to a design decision, not a coding mistake. Here is the two-hour session we run at the start of every build — and the template we use.
We rebuilt six sites this year. The same four fixes accounted for most of the gain every time — and image budgets were not the biggest one.
What we learned building a patient app for clinics where the connection drops every few minutes — and why sync conflicts are a product decision.
Need this done, not just read?
If any of the above sounds like a problem you have, a thirty-minute call with the engineer who wrote it is free.