Why late security is theatre
A security review at the end of a build finds the easy things and misses the structural ones. It can flag a missing header or an outdated dependency; it cannot easily undo an architecture where every service holds a master key because that was simplest to wire up in week two. By the time the review runs, the shape of the system is set, and the shape is where most real risk lives.
Secure by default inverts the order. The scoped role, the encrypted field, the configuration that refuses to start when a secret is missing — these are chosen at the moment the code is first written, when choosing them costs nothing. Security stops being a gate you pass before launch and becomes a property of how the thing is built, which is the only form of it that survives contact with a deadline.
What it looks like in the code
Scoped access first: every service, role, and token gets the narrowest set of permissions that lets it do its one job, so a compromise stays contained instead of spreading. Data sensitive enough to matter is encrypted at rest, and the keys are held apart from the data they open. None of this is exotic — it is just the default that too many systems skip because the broad grant was faster on the first day.
Then, configuration that fails loud. Runtime secrets and tenant-specific settings are read from a source of truth, never hardcoded, and a missing or malformed value stops the process cold rather than letting it limp along in a half-configured state. A system that silently degrades when its configuration is wrong is a system that will one day serve the wrong thing quietly, which is worse than an outage because no one notices.
No dev-only shortcuts
The most dangerous line in a codebase is the one that behaves differently depending on which environment it thinks it is in. A branch that skips a check when it detects development, a fallback that invents a default when a value is absent, a door left open because it was convenient locally — each is a shortcut that eventually ships, because the environment guess is eventually wrong. We do not write them. Every environment supplies its configuration explicitly, and what runs in production is what was tested everywhere else.
This is one thread of a larger commitment, and it connects directly to how data is isolated between customers — read the companion piece on per-tenant encryption. When we build for you, the same defaults come with it; the API layer we design is scoped and fail-loud from the start, not hardened afterward.