In 7 of the 21 third-party apps from my June and July 2026 audits, a confirmed authorization failure meant a logged-in user could read or write another customer’s data. When one check is the only control, one omission is a breach. Defense in depth is the design rule against that: put every important asset behind two or more independent layers.
What is defense in depth? Layered security, defined for an application
Defense in depth is a security design rule: protect every important asset with two or more independent controls, so that one bug, one leaked key or one misconfiguration cannot expose it on its own. Layered security is used for the same idea. Two checks that trust the same forged value count as one layer, not two.
Those 21 apps are a selected set of apps I audited, not a random sample, so that 7 in 21 is not a rate for AI-built apps in general. The individual controls that fill each layer are covered under web app security; this page arranges them into layers and leaves the how-to there.
The defense in depth definition in NIST’s glossary entry, taken from NIST SP 800-53 Rev. 5, reads: “An information security strategy that integrates people, technology, and operations capabilities to establish variable barriers across multiple layers and missions of the organization.” In plain words, defense in depth means no single security control is trusted to be perfect, so controls are stacked and kept apart, and one mistake should not defeat two of them at once. Another entry on the same defense-in-depth page, from NISTIR 8183, puts the goal as ensuring “that attacks missed by one technology are caught by another.”
What a layered defense is characterized by, in my reading, is independence rather than a count. If the API and the database policy both trust a user id the browser sent, a forged id gets past both at once, and you had one layer of defense wearing two names. In the same audits, 10 of the 21 third-party apps trusted the client: the server accepted whatever the browser asserted.
Layered security includes more than blocking. I count three jobs: preventing the attack, detecting it, and recovering from it, and the technical controls table further down gives one example of each per layer. Buying more tools does not add depth, and neither does pasting the same check into three files.
You will also see the rule called security in depth, sometimes hyphenated as security-in-depth; it means the same thing, so the definition above holds for it too. Some writers do draw a line between layered security and defense in depth, and the FAQ covers that split.
Layered cyber security for an office means firewalls, endpoint agents and VPNs. A hosted app has no office network to defend, so its cybersecurity layers sit at the edge, on the platform and in your own code, and that is where defense in depth applies to an application. Layering security controls only helps when each one can fail on its own without taking the next one with it.
The defense in depth layers, the model, and a diagram you can redraw for your app
Defense in depth layers have no standard count. ICS-CERT’s 2016 recommended practice lists 9 strategy elements for industrial control systems. For a hosted application my working model has 6: edge, platform, authentication, authorization in the API, authorization in the database, and detection and recovery. Draw one asset in the middle and name the control at each ring.
CISA’s defense-in-depth recommended practice (September 2016, written by ICS-CERT before CISA existed) is written for industrial control systems, and its Table 2 lists the elements in the left column below with three bullets each. The right column is my defense in depth model for a hosted web app, not CISA’s.
| CISA’s strategy element | What CISA lists under it | The hosted-app equivalent (my model) |
|---|---|---|
| Risk Management Program | Identify Threats; Characterize Risk; Maintain Asset Inventory | Choosing the assets that go in the middle of the rings |
| Cybersecurity Architecture | Standards/Recommendations; Policy; Procedures | The one-page policy further down |
| Physical Security | Field Electronics Locked Down; Control Center Access Controls; Remote Site Video, Access Controls, Barriers | Platform: the host’s infrastructure, which you do not run |
| ICS Network Architecture | Common Architectural Zones; Demilitarized Zones (DMZ); Virtual LANs | Platform: production, staging and previews kept apart |
| ICS Network Perimeter Security | Firewalls/One-Way Diodes; Remote Access & Authentication; Jump Servers/Hosts | Edge and authentication |
| Host Security | Patch and Vulnerability Management; Field Devices; Virtual Machines | Platform patching by the host, plus your dependency updates |
| Security Monitoring | Intrusion Detection Systems; Security Audit Logging; Security Incident and Event Monitoring | Detection and recovery |
| Vendor Management | Supply Chain Management; Managed Services/Outsourcing; Leveraging Cloud Services | Knowing which layer your host, auth provider and packages supply |
| The Human Element | Policies; Procedures; Training and Awareness | Who holds production access, and the review habit |
The two authorization layers have no row of their own in CISA’s list, which is aimed at plant networks. For a web app they are the inner rings, and they are the ones nobody supplies for you. CISA uses rings only for physical security, where it says “Classic physical security considerations typically refer to a ringed architecture of layered security measures.”
Here is the same model as a plain drawing. Detection and recovery sits outside the rings because it watches all of them.
+-----------------------------------------------------------------+
| EDGE: TLS, traffic filtering, rate limits |
| +-----------------------------------------------------------+ |
| | PLATFORM: machines, patches, environments, secrets | |
| | +-----------------------------------------------------+ | |
| | | AUTHENTICATION: who is making this request? | | |
| | | +-----------------------------------------------+ | | |
| | | | AUTHORIZATION IN THE API: may they do this? | | | |
| | | | +-----------------------------------------+ | | | |
| | | | | AUTHORIZATION IN THE DATABASE: row rule | | | | |
| | | | | | | | | |
| | | | | [ ASSET: customer records ] | | | | |
| | | | +-----------------------------------------+ | | | |
| | | +-----------------------------------------------+ | | |
| | +-----------------------------------------------------+ | |
| +-----------------------------------------------------------+ |
+-----------------------------------------------------------------+
DETECTION AND RECOVERY: logs, alerts, backups (watches every ring)
To turn it into a defense-in-depth diagram for your own app, put one asset in the middle: customer data, anything that moves money, or the AI bill. Then write the control that stops a stranger at each ring. An empty ring is the finding.
Why it matters for a small SaaS: secure architecture is the layers you actually have
Secure architecture for a small SaaS is the layer inventory filled in: for each layer, who provides it and what you still configure. The host and the auth provider supply part of the edge, platform and authentication layers. Authorization in the API and in the database, and detection, are the owner’s to build and to test.
The last column records what turned up where the layer was missing, across the 21 third-party apps I audited in June and July 2026. That is a selected group of apps, not a random sample, so read each count as a finding in those apps and nothing wider. The “who provides it” cells use Supabase and Vercel as the typical builder stack.
| Layer | Who provides it on a typical builder stack | What you must still configure | What my audits recorded where it was missing |
|---|---|---|---|
| Edge | Vercel serves every deployment over HTTPS and provides automatic DDoS mitigation for all deployments, regardless of plan | Rate limits on expensive endpoints and, where needed, firewall rules | 13 of the 21 third-party apps had no rate limiting on their most expensive endpoint |
| Platform | Supabase lists operating system maintenance and “infrastructure and the monitoring and security thereof” as its side | Keeping environments apart, and your secrets and API keys, which Supabase puts on the customer | 6 of the 21 third-party apps shipped a real secret |
| Authentication | The auth provider runs sign-in and sessions | Which routes and actions require a session | 11 of the 21 third-party apps had unauthenticated endpoints doing privileged work |
| Authorization in the API | Nobody: this layer is yours alone | The server decides who may act on which record, never the client | The client-trust count in the section above |
| Authorization in the database | Supabase provides row level security; applying it to each table is the customer’s job | Row level security or scoped queries on every table, as a second check behind the API | 9 of the 21 third-party apps had row-level security gaps |
| Detection and recovery | Supabase lists Postgres backups and observability as its side; error tracking in your code is not stated in Supabase’s model | Error tracking, alerts that reach a person, and a restore you have tried | 17 of the 21 third-party apps had no error tracking or alerting: when a user hits an error, nothing records it |
A cross-tenant failure like the ones counted at the top of this page is what you get when neither authorization row holds for a table. Vercel’s side of the platform row, and what it leaves to you, is set out in what Vercel secures and what stays yours, and the Supabase cells come from Supabase’s shared responsibility model. If the edge row is empty, start with rate limits and then decide how to set up a web application firewall for the routes that need more. The API row is tested the way an API security assessment does it, with two accounts. For the last row, the security events worth recording are part of how to prevent insufficient logging and monitoring.
Depth works even when a layer is flawed. I audited an AI coding workspace whose delete-file route pasted the user-supplied path into the database filter grammar instead of passing it as a value; the report bounds it honestly: the user-id filter and row-level security kept it inside the caller’s own workspace, but a crafted path could delete more of their own files or break the query, and the full telling belongs to input validation for a web app. The lesson I take from it is that two layers held while one failed, and the failed one still needed fixing.
In my reading, security architecture for an app this size is that table filled in and kept current, not a separate diagram genre. The habit that makes the inner rings matter is assume breach, which Microsoft’s zero trust overview puts as: “Security controls are designed with the expectation that attackers might be operating inside the environment.” Applied to the inventory, design each layer as if the one outside it has already failed.
Zero trust is the same idea applied to identity and access. NIST SP 800-207 says zero trust “assumes there is no implicit trust granted to assets or user accounts based solely on their physical or network location”. You don’t need zero trust tools to apply that to a hosted app: check identity and permission on every request, wherever it comes from. Deciding which assets need every ring, and which can live with fewer, is threat modeling.
How it works: controls, design principles, and the process that keeps them in place
The layers are made of controls, the controls follow a handful of design principles, and a development process keeps them from quietly disappearing. The five parts below go from the concrete to the organizational.
Technical security controls, with examples by layer
Technical security controls are the ones the system enforces by itself, such as an auth check, a database policy, a rate limit or an alert. I group them by function into preventive, detective and corrective controls. Depth needs all three, because prevention with no detection fails without anyone noticing.
NIST’s glossary sorts controls by nature instead: “The management, operational, and technical controls (i.e., safeguards or countermeasures) prescribed for an information system”. Technical controls are those “primarily implemented and executed by the information system through mechanisms contained in the hardware, software, or firmware components of the system.” The function split is my own lens, not NIST’s wording, and the examples of technical controls in the table are mine: one preventive, one detective and one corrective per layer.
| Layer | Preventive | Detective | Corrective |
|---|---|---|---|
| Edge | A rate limit on signup and on the AI endpoint | An alert when blocked requests spike | Tighten the limit or block the source |
| Platform | Secrets only in the host’s environment settings | Secret scanning on every push | Rotate the leaked key |
| Authentication | A session required on every protected route | A log of failed sign-ins | Revoke sessions and force a new sign-in |
| Authorization in the API | A server-side permission check on every request | A log of denied requests per user | Fix the check and review the records it exposed |
| Authorization in the database | A row policy that denies by default | A second-tenant test that should return nothing | Restore damaged rows from a backup |
| Detection and recovery | Backups on a schedule, so any loss has a limit | Error tracking with alerts | A restore you have already rehearsed |
Read the table by column: a column with blanks is where a failure would go unseen. Administrative controls for a two-person team are short: who has production access, how it is removed, and the one-page policy below.
Secure design principles: the eight from 1975, OWASP’s list, and secure by design
Secure design principles trace back to a 1975 paper by Jerome Saltzer and Michael Schroeder that named 8: economy of mechanism, fail-safe defaults, complete mediation, open design, separation of privilege, least privilege, least common mechanism and psychological acceptability. Defense in depth is absent from the list, yet several of them add up to it when applied to one asset.
Saltzer and Schroeder’s 1975 paper calls them “eight examples of design principles that apply particularly to protection mechanisms.” The middle column quotes each one’s opening line; the right column is my reading for an AI-built app.
| Principle | The paper’s words | What it looks like in an AI-built app |
|---|---|---|
| Economy of mechanism | ”Keep the design as simple and small as possible.” | One permission helper every route calls, not a check rewritten in each file |
| Fail-safe defaults | ”Base access decisions on permission rather than exclusion.” | Deny by default in every database policy; a new table starts closed |
| Complete mediation | ”Every access to every object must be checked for authority.” | Permission checked on every request, not once at login |
| Open design | ”The design should not be secret.” | No reliance on a hidden URL or an unguessable id |
| Separation of privilege | ”Where feasible, a protection mechanism that requires two keys to unlock it is more robust and flexible than one that allows access to the presenter of only a single key.” | Two independent checks on the same record: the API and the database |
| Least privilege | ”Every program and every user of the system should operate using the least set of privileges necessary to complete the job.” | Server code uses the narrowest key; the service key never reaches the browser |
| Least common mechanism | ”Minimize the amount of mechanism common to more than one user and depended on by all users” | No query or cache shared across tenants without a tenant filter |
| Psychological acceptability | ”It is essential that the human interface be designed for ease of use, so that users routinely and automatically apply the protection mechanisms correctly.” | A control people work around is no control: an admin check so slow the team adds a bypass flag |
The paper’s case for fail-safe defaults is that the opposite habit “presents the wrong psychological base for secure system design.” Psychological acceptability is the security principle behind the last row, and it matters for a small team: a rule that gets in the way gets switched off. As a security principle, economy of mechanism asks for one small, shared permission helper; least common mechanism adds that nothing shared between tenants may skip it. How complete mediation carries through each individual control is part of web app security, not this page. The open design rule, in cybersecurity terms, is to assume the attacker has read your code.
OWASP’s security principles, as its Developer Guide lists them today, run to 16 headings, starting with Security by Design and Security by Default, with Defense in Depth fourth. That list of fundamental security design principles reuses most of the 1975 names. OWASP’s Secure Product Design Cheat Sheet is shorter, with four OWASP principles: least privilege and separation of duties, defense-in-depth, zero trust, and security-in-the-open. Where the lists come from, and what OWASP is, matters less here than what they say.
Security design, in one sentence, is choosing these before the code exists rather than bolting them on after. For a small app, cyber security design is mostly the principles table applied to the layer inventory, in my reading.
Secure by design, as CISA uses it, puts the burden on the maker. CISA’s Secure by Design page says “the cybersecurity burden is placed disproportionately on the shoulders of consumers and small organizations and away from the producers of the technology”. Its October 2023 joint guidance lists the security by design principles as three: Take Ownership of Customer Security Outcomes, Embrace Radical Transparency and Accountability, and Lead From the Top. For your own customers, you are the producer.
Secure software design with an AI assistant has one extra gap, in my reading: AI-generated code follows the prompt, and a prompt rarely states any of these principles. That is why the inner layers are the ones that tend to be missing.
OWASP Top 10 Proactive Controls: the builder’s list
The OWASP Top 10 Proactive Controls are a list of controls to build into an application, the counterpart of the Top 10 list of what goes wrong. They work as a build checklist beside the layer inventory: most are preventive layers, and logging and monitoring is the detective one.
The project describes its goal as “to raise awareness about application security by describing the most important areas of concern that software developers must be aware of.” There is no 2021 or 2023 edition of the OWASP Top 10 Proactive Controls: the project site lists editions from 2014, 2016, 2018 and 2024, plus a future list marked as work in progress. The 2018 list is still online if you meet it in an older questionnaire, but the 2024 list is the one to build against.
The 2024 list, on the OWASP Top 10 Proactive Controls site, runs from C1: Implement Access Control to C10: Stop Server Side Request Forgery. In my mapping, C1 lives in both authorization layers; C3: Validate all Input & Handle Exceptions and C5: Secure By Default Configurations are preventive controls in every layer; C6: Keep your Components Secure belongs to the platform; and C9: Implement Security Logging and Monitoring is the detection layer. Tick each one against the inventory rather than reading it as a separate program.
Secure development practices: the SDLC, DevSecOps, BSIMM, SAMM and the SSDF
Secure development practices keep layers from decaying between releases. My small-team working rule is six habits: reviewed changes to the main branch, CI with tests and a dependency scan, secret scanning, a place to test before production, a pull request security question, and a named owner of production access. BSIMM, SAMM and the SSDF describe larger programs.
Secure software, in the development sense, is software built and checked so it keeps its promises while someone is trying to break it. NIST SP 800-218, the SSDF starts from the observation that “Few software development life cycle (SDLC) models explicitly address software security in detail”, and organizes its practices into four groups: Prepare the Organization, Protect the Software, Produce Well-Secured Software, and Respond to Vulnerabilities.
| Framework | Who publishes it | What it describes | Does a two-person team need it? (my reading) |
|---|---|---|---|
| SSDF (NIST SP 800-218, version 1.1) | NIST | ”a core set of high-level secure software development practices that can be integrated into each SDLC implementation”, in four practice groups | Not as a program; its four group names are handy vocabulary |
| BSIMM | Black Duck | ”a descriptive model that provides a baseline of observed activities for software security initiatives”: 12 practices in four domains | No: it benchmarks larger security programs |
| OWASP SAMM | OWASP | ”five business functions and fifteen security practices” | Later, as a self-check once there is a team to measure |
The four BSIMM domains are Governance, Intelligence, SSDL Touchpoints and Deployment. OWASP SAMM names its business functions Governance, Design, Implementation, Verification and Operations. No web application security framework in that table is aimed at a two-person team, in my reading. When a buyer asks which application security framework you follow, the honest answer names the practices you actually run, and the SSDF’s group names are a fair way to label them.
In SDLC terms, DevSecOps means the security checks run in the same pipeline as the tests, on every change. My SDLC security checklist for a small team is six items, my working rule, and each one is a habit before it is a tool:
- Reviewed changes to the main branch. GitHub’s protected branches and rulesets cover public repositories on GitHub Free, and private ones on GitHub Pro, Team and Enterprise Cloud; on a private repository without them, keep a review habit and a named reviewer.
- CI that runs the tests and a dependency scan on every pull request.
- Secret scanning. Push protection for a repository requires GitHub Secret Protection to be enabled and is off by default; push protection for your own account is on by default and stops pushes of secrets to public repositories.
- A place to test before production, with its own database.
- A security question in the pull request template: what can a user reach now that they could not reach before?
- A named owner for production access, who also removes it when someone leaves.
For the test environment item, setting up a staging environment before your first deploy breaks something is its own short job. These are the software development security best practices I’d have in place first; secure SDLC tools are the scanners those steps call, and which ones depends on your stack, so there is no tool list here. What a human reviewer adds on top is what a security review checks.
The application security policy: one page, not a template pack
An application security policy for a small SaaS fits, by my working rule, on one page of eight lines: production access, secrets, authorization on the server and in the database, dependency updates, logging and alerts, the release path, vulnerability reports, and the review date. Each line needs a control behind it, or a questionnaire answer will rest on nothing.
When a buyer asks for your security policy, they mean a short statement of rules the team holds itself to, not a binder. The block below works as a web application security policy template: copy it, fill the brackets, and cut any line you cannot make true today.
Application security policy for [product], owner: [name], reviewed [date]
1. Production access: only [names] can reach production; access is removed the day someone leaves.
2. Secrets: stored in [secret store or host settings], never in the repository; rotated after any exposure.
3. Authorization: every request is authorized on the server and again in the database.
4. Dependencies: updates reviewed [how often]; known-vulnerable packages fixed within [time].
5. Logging and alerts: errors and security events are logged; [name] is alerted.
6. Changes: every change reaches production through a reviewed pull request and CI.
7. Vulnerability reports: received at [address]; acknowledged within [time].
8. Review: this policy is reviewed every [period] by [name].
At this size, a secure organization is one where those eight lines are true and each has a named owner. A line with nothing enforcing it is only a promise, and the difference between a policy and a control is the question behind that.
How to check your own app: the set-one-layer-aside test
Defense in depth is tested by setting one layer aside at a time. With the API check skipped, the database should still refuse another tenant’s rows. With the database policy out of the path, the API should still refuse. Expensive endpoints should refuse or rate limit a caller with no session. A forced error should reach a person.
Run these five checks on a staging copy of an app you own, with test accounts, never on anyone else’s system. Keep the evidence each one names.
- 01 Pick the assets that matter: customer records, anything that moves money, and the AI or compute bill. Fill one inventory table per asset. Fail: a ring with nothing written in it. Evidence: the filled table, dated.
- 02 The database layer alone. On a stack whose database the browser can reach, such as Supabase's data API, sign in as a test user of tenant A and request a row belonging to test tenant B directly, skipping your API. A correct row level security setup returns an empty result for the read, not an error. Fail: tenant B's row comes back. Evidence: the request and the response. If only your server reaches the database, this layer is the scoped query in server code, and you test it as in the next check on a second route.
- 03 The API layer alone. Call the endpoint with a valid session for test tenant A and a record id that belongs to test tenant B. Fail: the record loads or changes. Evidence: the request and the response status.
- 04 The edge layer. Call an endpoint that should need a session with no session at all. Fail: it does the work. For a public, expensive endpoint, send a short burst from one test client above the limit you set, then one normal request from a second client. Fail: the burst is never limited once it passes the allowance your limiter documents, or the second client is refused. Evidence: the response codes, in order.
- 05 The detection layer. Force one error on a test route, or trigger the exact condition your alert watches if it fires on a rate rather than one error. Confirm the alert reaches its person within the delay your alerting tool states. Fail: nobody is told. Evidence: the alert, with its timestamp.
A blocked read in row level security fails silently, which is why the database check looks for an empty result rather than an error; the full method is in how to verify whether RLS is enough. The two-account request in the API check is the same method the API security checklist uses.
A finding in one check while the neighboring layer holds is depth doing its job. The same asset failing both the database check and the API check is a single-layer design, in my reading.
In the Production Hardening Sprint, two deliverables are checked the same way. Deliverable 1.3 is verified this way: “Call protected actions directly as unauthorized and underprivileged users; confirm rejection.” Deliverable 1.4 is verified this way: “Run read and write tests as anonymous users, different roles, and separate tenants.”
Where the sprint fits
No deliverable is named “defense in depth”; four of them match layers above. Deliverable 1.3, Server-side authorization: “Enforce permissions on every protected route, API endpoint, and server action.” Deliverable 1.4, Data isolation across every table: “Implement and test Row-Level Security or equivalent server-side scoping across all tables, with explicit rules for intentionally public data.” Deliverable 3.6, Public-endpoint rate limits: “Protect public forms, signup flows, and resource-consuming endpoints with appropriate limits.” Deliverable 8.3, Operational threshold alerts: “Alert on error spikes, latency, connection pressure, and queue backlog.” Formal third-party certifications and independent audit opinions are separate from these engineering deliverables. Each one is listed in the published scope.
Common questions about layered security
What is the difference between defense in depth and layered security?
Often there is none: OWASP’s Developer Guide introduces defense in depth as “Also known as layered defense”, and this page treats the two as one idea. Writers who split them make layered security the narrower term. Legit Security, a security vendor, puts it as “Defense in depth is the big-picture strategy, while layered security is one way of carrying that strategy out.”
What is military defense in depth?
Military defense in depth is a strategy that slows an attacker through successive positions instead of trying to stop them at one line, trading ground for time. The security sense borrows the core of it: no single line is expected to hold, so the next one has to be ready.
What are the 7 principles of secure by design?
CISA does not publish seven secure by design principles: its October 2023 guidance names three, and seven is the number of goals in its Secure by Design Pledge. The pledge goals are multi-factor authentication, default passwords, reducing entire classes of vulnerability, security patches, a vulnerability disclosure policy, CVEs, and evidence of intrusions.
What are the three elements of layered security?
In the grouping this page uses, the three elements are preventive, detective and corrective controls: stop the attack, notice it, and recover from it. Other sources group them differently; NIST’s glossary, for one, divides controls into management, operational and technical.
The checks in this guide show you where the app is open. The sprint below closes those gaps, tests the result and writes the evidence down.
Built it with AI. Now it has to hold up for real customers.
The Production Hardening Sprint takes the app you already have and builds the production foundation underneath it. Authentication and access rules, payments that stay consistent, error handling, monitoring, backups, automated tests and a documented handover. Our engineers work inside your existing codebase for ten working days. All 123 deliverables are included, and you get the evidence for each one.
See the Production Hardening Sprint →
$2,500 fixed price · 10 working days · One codebase