Security-First Architecture: Patterns I Use on Every Project
Why Security from Day One
Having studied cybersecurity at IIT Guwahati, I have seen the academic side of security. But production systems teach you a different lesson: retrofitting security is 10x harder than building it in. A SaaS client once asked me to add role-based access control to a system that was built without any authorization layer. What should have been a two-day feature turned into a three-week refactor because permissions needed to be threaded through every API endpoint, every database query, and every UI component.
Input Validation at the Boundary
Every piece of data that enters your system — API request bodies, URL parameters, file uploads, webhook payloads — should be validated and sanitized at the boundary. I use Zod for TypeScript projects because it gives you both runtime validation and compile-time types from a single schema definition. The pattern is simple: define your schema once, use it to validate incoming data, and let TypeScript infer the types for your handlers. No request reaches business logic without passing validation first.
The Principle of Least Privilege
Every component in the system — database users, API keys, service accounts, IAM roles — should have exactly the permissions it needs and nothing more. Your web application does not need database admin rights. Your CI pipeline does not need production write access. Your frontend API key does not need access to admin endpoints. I enforce this by creating separate database roles per service, scoping API keys to specific operations, and using short-lived tokens wherever possible.
Secrets Management
Never commit secrets to version control. This sounds obvious, but I have found API keys in git history on nearly every inherited codebase I have audited. My standard setup: environment variables for local development (with .env in .gitignore), a secrets manager (AWS Secrets Manager or Vercel Environment Variables) for production, and pre-commit hooks that scan for patterns matching API keys, tokens, and passwords. If a secret is ever exposed, rotate it immediately — do not just remove the commit.
Dependency Security
Your application is only as secure as its weakest dependency. I run npm audit or pip audit on every CI build and treat high-severity vulnerabilities as build failures. For critical applications, I pin exact dependency versions and review changelogs before upgrading. Dependabot or Renovate for automated PRs, but never auto-merge — a compromised package update is one of the most common supply chain attack vectors.