Problem Statement
Every new SaaS product requires the same foundational plumbing: authentication, multi-tenancy, billing, permissions, and background job processing. Building this from scratch each time wastes weeks of engineering effort and often introduces subtle security or isolation bugs. The goal was to produce a robust, reusable boilerplate that teams could fork and build product features on top of immediately — with none of the typical corner-cutting that leads to rework later.
Key Challenges:
- Strict tenant data isolation without global query filters being missed by developers
- Flexible role-based access control that scales from simple to complex permission trees
- Subscription lifecycle management across free, trial, and paid tiers
- Rate limiting that is tenant-aware and configurable per plan
- Developer experience that does not sacrifice correctness for speed
System Architecture
The boilerplate is structured around independent domain modules — auth, tenants, billing, permissions, jobs — each with clear boundaries and no cross-module database queries. FastAPI provides the API layer; PostgreSQL with row-level security enforces tenant isolation at the database level; Celery handles background work; Redis manages caching and rate limiting.
Tenant Isolation
PostgreSQL row-level security policies enforce that queries only return rows belonging to the requesting tenant, with application-level middleware setting the current tenant context on every request.
Auth & Permissions
JWT-based authentication with short-lived access tokens and rotating refresh tokens. RBAC system supporting hierarchical roles, resource-level permissions, and per-tenant permission overrides.
Subscription Management
Plan definitions with feature flags and usage limits stored per tenant. Webhook handlers process payment provider events to activate, upgrade, downgrade, or suspend tenant access automatically.
Background Jobs
Celery worker pool with Redis broker handling async tasks: emails, report generation, bulk operations, and scheduled jobs. Tasks are tenant-scoped and respect plan-level execution priority.
Key Engineering Challenges
Tenant Data Leakage Prevention
Challenge: Application-level filters can be forgotten or bypassed by developers adding new queries, risking cross-tenant data leakage.
Solution: PostgreSQL row-level security as the enforcement layer — even a raw SQL query without a filter returns zero rows for the wrong tenant, making leakage structurally impossible.
Flexible Permission Modelling
Challenge: Different SaaS products need different permission semantics — simple roles vs. fine-grained resource-level ACLs.
Solution: Layered permission system: global roles define broad access, resource-level overrides allow per-record exceptions, and tenants can define custom roles within plan limits.
Rate Limiting Across Distributed Workers
Challenge: Rate limits must be enforced consistently even when multiple API instances are running behind a load balancer.
Solution: Redis-based sliding window counters keyed by tenant and endpoint, providing consistent rate state across all API instances without a centralised bottleneck.
Developer Ergonomics
Challenge: Security infrastructure tends to add friction to development if not designed carefully, causing developers to work around it.
Solution: Dependency injection patterns in FastAPI make tenant context, user identity, and permission checks declarative one-liners at the route level with no repetitive boilerplate.
Solutions Implemented
- Row-Level Security: PostgreSQL policies automatically scoping all queries to the current tenant context, enforced at the database engine level.
- JWT Auth Pipeline: Access token issuance, refresh rotation, token revocation list in Redis, and per-device session management.
- RBAC Engine: Hierarchical roles with inheritance, resource-level permission overrides, and plan-gated feature flags evaluated at request time.
- Subscription Webhooks: Idempotent event handlers processing payment provider callbacks to manage tenant access states reliably.
- Dockerised Dev Environment: One-command local setup with Postgres, Redis, Celery worker, and API service; production-parity configuration via environment variable schema validation.
Outcome & Impact
Per new SaaS project
Due to DB-level enforcement
Each domain independently replaceable
Security & observability included