Every security program has a version of the same plan: train developers, publish guidelines, ask them to remember. Then a hardcoded key lands in a repo, an endpoint ships without auth, and someone schedules another training.
The training isn't the problem. The plan is. If security only happens when a busy engineer remembers to choose it, you've built a system that fails on the busiest day of the quarter.
Secure by default engineering flips that. The safe option is the one developers get without asking, and the insecure one takes deliberate effort.
Most security programs quietly assume a developer who is always alert, always informed, and always willing to trade speed for safety. That person doesn't exist at scale, and it's not a character flaw.
Developers are measured on what they ship. Sprint commitments, release dates, and customer requests set their priorities, so when a secure option costs extra time, it competes with the deadline. The deadline wins most of the time.
That's rational behavior inside the incentives you gave them. If your security model depends on people acting against their incentives, the model is the thing to fix.
Insecure choices rarely come from ignorance. They come from context.
Awareness campaigns address none of this. Knowing the right answer doesn't help when the right answer costs twenty minutes you don't have.
Friction in security tooling does more than slow people down. It teaches them to route around you.
A scanner that returns hundreds of unprioritized findings gets ignored. A review gate that blocks merges for days gets bypassed with an exception. A policy that requires a separate portal, a ticket, and a manual approval gets skipped for anything that feels low-risk, and developers decide what feels low-risk.
Each workaround also has a second cost: you lose visibility. The team that quietly bypasses a control is the team your security staff can't see. For fintechs in the seed-to-Series-B range, where there may be one or two security people (or none) supporting a growing engineering org, that lost visibility is hard to recover.
Friction is a security risk in its own right.
A secure default isn't a stricter policy. It's a better starting point. A few design principles hold up in practice:
These are illustrative patterns, not a prescription for any single stack.
Secrets. Instead of reminding developers not to commit credentials, add a pre-commit and CI check that blocks them, and give the team a secrets manager that's easier to use than pasting a key into a config file. The check catches mistakes, and the easy alternative reduces them.
Infrastructure. Publish approved infrastructure-as-code modules where storage is encrypted, public access is off, and logging is on. A developer who copies the module gets the secure configuration without knowing the details.
Application code. Use a framework setup where authentication and input validation are middleware applied to every route, rather than something each developer wires up per endpoint. Forgetting becomes harder than remembering.
Dependencies. Automate update pull requests and run vulnerability checks in CI, with a clear threshold for what blocks a build. Developers see the problem in the same place they see failing tests.
Cloud and runtime. Check configuration against baseline rules automatically, so a misconfigured resource gets flagged the day it's created instead of the day it's exploited.
In each case, the developer's normal workflow is the security workflow. Nobody had to attend a session.
Skip vanity metrics like training completion rates. They measure effort, not outcomes. Better signals:
Review these with engineering leadership, not just security. If the numbers only improve when security pushes, you haven't made it a default yet.
Don't make developers choose security. Make security the default choice.
Your engineers aren't the weak link. They're doing what the system rewards. Change what the system rewards, and the behavior follows.
Next step: See what secure by default development looks like in practice.