Threat modelling at design time: A field guide
A penetration test six weeks before launch can't fix architectural insecurity. Threat modelling at design time is the practice that prevents the bug — not the test that finds it. Here's how we run it.
Most security findings on our VAPT reports would have been impossible to introduce if someone had spent four hours threat-modelling the design six months earlier. That's not hindsight — it's a depressingly reliable pattern across 80+ engagements.
VAPT finds bugs. Threat modelling prevents architectural classes of bug. The cost difference is roughly two orders of magnitude. This is the field guide we teach our clients.
What threat modelling actually is
Strip away the frameworks for a moment. Threat modelling is a structured conversation that produces three artefacts:
- A diagram of what's being built — components, trust boundaries, data flows
- A list of threats against each trust boundary, classified by severity
- A list of mitigations — controls, design changes, or accepted-risk decisions, signed off by name
That's it. The structure matters. Decorative threat models are theatre.
When to run it
Twice on every system:
- At design time, when the architecture is still cheap to change. Before the first line of code.
- At major change, whenever a new trust boundary is introduced (a new external API consumer, a new data source, a new region).
The one-time threat model that gets done as a compliance tickbox produces a PDF that no engineer ever reads. The recurring threat model that runs at design time becomes part of how the team thinks.
The frame we use: STRIDE, applied pragmatically
STRIDE asks six questions of every trust boundary:
| Threat | Question |
|---|---|
| Spoofing | Can the attacker pretend to be someone else? |
| Tampering | Can the attacker modify data or code? |
| Repudiation | Can a user deny actions they took? |
| Information disclosure | Can the attacker read data they shouldn't? |
| Denial of service | Can the attacker take the system down? |
| Elevation of privilege | Can the attacker gain capabilities they shouldn't have? |
For each component on the diagram, walk through all six. Most components only have two or three relevant threats. Skip the irrelevant ones explicitly — "Repudiation: not applicable, no user actions cross this boundary" — so future-you knows it was considered.
The discipline that makes it stick
The threat modelling I see fail uses STRIDE as a checklist and produces a list of generic threats no one acts on. The version that works adds three disciplines:
Sign every mitigation
Every threat resolves to one of three: a control, a design change, or an accepted-risk decision. Each is signed by a person — not a team. "PII at rest: encrypted with KMS-managed keys, rotated quarterly. Owner: Amara Eze."
Anonymous mitigations are aspirational. Signed ones get done.
Re-test the assumptions
Threat models capture assumptions: "the load balancer terminates TLS"; "the database is reachable only from the application VPC." Six months later, those assumptions drift. Quarterly review re-validates them.
Tie findings to the same backlog as feature work
Threats in a separate spreadsheet die in the spreadsheet. Threats that produce backlog items, sized and prioritised alongside features, get shipped.
Common findings we see, by trust boundary
After running threat models on many engagements, the same architectural patterns surface:
- Mobile → API: Most apps trust their own clients too much. Server-side validation duplicates client-side validation; rate limits enforced at the API gateway, not the application; certificate pinning where the threat justifies it.
- Third-party integration → internal service: The third party is treated as trusted because they're a "vendor." They're not. A compromised vendor is a routine attack vector. Vendor APIs should be quarantined behind their own service with explicit validation.
- Background jobs → core database: Async workers often have privileges they don't need because "they're internal." A compromised worker becomes a privilege escalation path.
- Logging pipelines → object storage: PII in logs is the silent breach. Redaction at the source, not in the warehouse.
What this costs
A first-time threat model of a moderately complex system: 4–8 hours of senior engineering time. Subsequent reviews: 1–2 hours.
A penetration test of the same system, six months later: 3–6 weeks of consultant time, plus the engineering time to fix what's found, plus the slipped launch date, plus the audit finding from the things that didn't get fixed.
The math is not subtle. Threat modelling is the highest-ROI security practice we know.
If you're starting now
Three concrete steps:
- Pick one system you're about to design. Schedule four hours next week.
- Draw the diagram on a whiteboard. Components, trust boundaries, data flows. Photograph it; don't fancy it up in a tool.
- Walk STRIDE. Capture threats and assign mitigations with owners. Put the doc in the same repo as the system's code.
That's the entire practice. Repeat every quarter. After three cycles it becomes muscle memory and your security posture quietly transforms.
We run threat-modelling workshops for client engineering teams. The format is two days, hands-on, on your real systems. Most clients tell us afterwards that they'd been doing "security review" for years without ever actually threat-modelling. That gap is what we close.
15 years across payments, telco, and platform engineering. Founded Hexcore to prove African engineering can ship at world-class standards.

The four practices that turn a launch into a durable product
Most launches succeed. Most products fail soon after. The gap is not engineering talent — it's a set of operating practices that the strongest teams treat as defaults. Here are the four we install on every Hexcore engagement.

Boring on purpose: why Go quietly won the modern backend
Go was never the fashionable choice. It was always the durable one. Here's why we reach for Go first when we're building backend services that have to last — and the specific patterns we use to keep them clean as the codebase grows.

Why your RAG demo doesn't survive production
A working LLM prototype and an enterprise-grade RAG system are separated by a body of unglamorous infrastructure: evals, guardrails, observability, cost controls, drift detection. Here's the checklist we use to close the gap.