Skip to content

Security

Security in The Unsexy Stack is hardened by default, not left as an exercise. The download includes a security checklist of 20 items mapped to OWASP ASVS Level 1 (the canonical customer-facing claim; the full checklist also covers additional pre-launch items).

  • Rate limitingslowapi on the API surface, so a single client cannot hammer endpoints.
  • Locked-down CORS — an explicit allow-list, not a wildcard.
  • Structured logging with request IDs — every request is traceable end-to-end.
  • Pydantic v2 validation — request bodies are validated and typed at the boundary, so malformed input is rejected before it reaches your logic.
  • Signature-verified webhooks — Stripe events are verified before processing (see Billing).
  • JWKS-cached RS256 auth — with a thundering-herd guard (see Auth).

The shipped docs/SECURITY_CHECKLIST.md walks the 20 OWASP ASVS L1 items with where each is handled in the codebase, plus a set of pre-launch items (secrets handling, HTTPS, headers) you tick off before going live. It is a checklist you can hand to a reviewer, not a marketing bullet.

Single-tenant by design (an opinionated choice)

Section titled “Single-tenant by design (an opinionated choice)”

The Unsexy Stack is single-tenant by default, and that is deliberate. We do not push tenancy into Postgres row-level-security policies, because splitting application logic across database policies makes local testing, migrations, and schema evolution brittle for a lean team — the exact team this stack is for. Instead, tenancy is an explicit, testable check at the application boundary via FastAPI’s dependency injection, where you can read it, debug it, and cover it with a test. When you do need B2B multi-tenancy, the patterns to extend are clean and documented — but the production baseline you ship on day one is the simple, hardened, single-tenant core. Honestly scoped, and opinionated on purpose.