Skip to content
← All perspectives
Secure by Design

Security is a design property, not a control count

The strongest systems I've worked on weren't the ones with the longest list of tools. They were the ones where the dangerous thing simply couldn't happen — because the design didn't allow it. Here's how to think that way on purpose.

Ask most teams how secure their system is and you'll get an inventory: a WAF, an EDR agent, an SIEM, MFA, a quarterly pen test. It's a reasonable answer to the wrong question. A pile of controls tells you what was bought. It doesn't tell you what can still go wrong.

The systems I trust most are boring in a very specific way: the failure you're worried about isn't mitigated, monitored or accepted as residual risk — it's structurally impossible. The credentials can't leak because they were never in the code path. The blast radius is small because the boundary was drawn before the first line was written. Security stopped being a layer on top and became a property of the shape.

That shift — from counting controls to designing away failure modes — is the whole game. Everything else is bookkeeping.

Controls are a tax; design is an investment

Every control you add has a running cost. Someone tunes it, patches it, pays for it, and gets paged by it at 3am. Controls are how we buy down risk we couldn't design out — and sometimes that's genuinely the right call. But reach for them first and you end up with a system held together by vigilance, where safety depends on twelve things all working at once, forever.

Design works the other way. It costs more up front — the thinking is harder, the arguments are longer — and then it keeps paying you back, quietly, every day nobody has to think about it.

A control mitigates a bad thing that can happen. A good design means the bad thing can't happen. Prefer the second one whenever you can afford the thinking.

A quick example. Say a service needs to read from a database. The control-first answer is a secret in a vault, rotation, an alert if it's read from an odd place, and a detection rule for exfiltration. The design-first answer is a workload identity the platform issues and rotates automatically, scoped to exactly that one table, that the application code never sees and therefore can never leak. The second version deletes an entire category of incident instead of watching for it.

Three questions that move you from controls to design

You don't need a heavyweight methodology to think this way. On any component, I ask three things in order, and I don't let the conversation move on until each one has a real answer.

1. What must be true for this to be safe?

Not "what could go wrong" — that list is infinite and demoralising. Instead: what are the load-bearing assumptions? "Only this service can write to this bucket." "This token is never valid off-network." "A compromised worker can't reach the control plane." Write them down as flat, checkable statements. Those sentences are your security architecture. Everything else is in service of keeping them true.

2. Where does that truth live — in the design, or in someone's diligence?

Take each assumption and ask what enforces it. If the answer is "an IAM policy the platform won't let you violate," good — it lives in the design. If the answer is "we told the developers not to," "there's a Slack reminder," or "the reviewer usually catches it," then it lives in diligence, and diligence has a failure rate. The goal of every review is to migrate assumptions from the second column to the first.

3. When it fails anyway, how far does it get?

Assume the boundary breaks — because eventually one will. The question that separates a bad day from a breach is reach. One credential, one host, one tenant, one region: how much does an attacker inherit when they land? Blast radius is a design decision you make months before the incident, and it's the single highest-leverage thing you can get right.

The test I actually use

For any control on a diagram, I ask: "If this were switched off tomorrow, would the system still be safe, or just quieter?"

If it'd still be safe, the control is defence in depth — keep it, it's earning its place. If the system would be genuinely exposed, that control is load-bearing, and load-bearing controls belong in the architecture, not bolted on beside it where a config change can remove them.

"Secure by design" is not the same as "secure by default"

The two get used interchangeably and they shouldn't. Secure by default is about the starting position — the box ships locked, the flag is off, the bucket is private until you deliberately open it. That matters, and it's cheap safety.

But secure-by-design goes further: it's about which mistakes the system will even let you make. A secure-by-default database still lets a tired engineer make it public at 5pm on a Friday. A secure-by-design platform makes "public" a privileged, logged, four-eyes action that a single person can't do by accident. Defaults protect you on day one. Design protects you on the ten-thousandth day, when everyone's forgotten why the default was there.

Defaults decide where you start. Design decides what the system will let you do wrong later — and "later" is where breaches actually live.

Where this leaves the frameworks

None of this is an argument against NIST CSF, CIS, ISO 27001 or a cloud well-architected review. I use all of them. But I use them as a lens, not a shopping list. A framework is brilliant at telling you which questions you forgot to ask. It's terrible at telling you the answer for your system — that's the architect's job, and it's the part you can't outsource to a checklist.

So the sequence I try to hold to, in order:

  • Understand — map the assets, the data flows, the trust boundaries, and the threat model that actually applies to this system, not the one in the whitepaper.
  • Architect — design the failure modes out where you can, so the load-bearing assumptions are enforced by the platform, not by hope.
  • Assure — then bring the framework, to prove the design holds, evidence the controls, and find the questions you missed.

Do it in that order and the controls you end up with are the ones that matter, each traceable to an assumption you're deliberately protecting. Do it in reverse — framework first — and you get a system that passes the audit and still can't answer question three.


Security that's designed in isn't about doing more. Most of the time it's about doing less, earlier, in the one place where a decision is still cheap to change: the diagram, before anyone's written the code. Count your controls if you like. But judge your architecture by the incidents that can no longer happen.

JV

JV · Security Architect

I design secure-by-design, zero-trust and well-architected cloud systems — and write about the trade-offs behind them. This site is my portfolio.