ForgeStack
A production-ready, multi-tenant SaaS starter kit with enterprise-grade security.
View RepositoryAt a glance
Accelerate SaaS development with a battle-tested foundation that handles multi-tenancy, authentication, and authorization out of the box.
Engineering teams and solo founders building B2B SaaS products who need enterprise-grade infrastructure without the months of setup time.
- • True multi-tenancy with tenant isolation at the database level
- • Role-based access control (RBAC) with granular permissions
- • PostgreSQL Row Level Security (RLS) for data isolation
Context
Building a SaaS product from scratch requires solving the same foundational problems repeatedly: authentication, authorization, multi-tenancy, and data isolation. These aren't differentiated features—they're table stakes. Yet getting them wrong can sink a product.
The Problem
Most SaaS starters cut corners on multi-tenancy. They either use tenant columns (leaky abstraction, error-prone) or separate databases (expensive, operationally complex). Neither approach provides the security guarantees enterprise customers demand.
Approach
ForgeStack implements true multi-tenancy using PostgreSQL's Row Level Security at the database layer. This means tenant isolation is enforced by the database itself—not application code that can have bugs. Combined with a strict RBAC system, it provides defense in depth.
Architecture
ForgeStack uses a monorepo structure with clear separation between the Next.js frontend and NestJS backend. Turborepo handles build orchestration, while pnpm workspaces manage dependencies. The backend exposes a typed API that the frontend consumes, with end-to-end type safety via shared types.
The architecture prioritizes developer experience without sacrificing production readiness. Hot reload works across the entire stack, and the testing infrastructure supports unit, integration, and e2e tests out of the box.
apps/
├── web/ # Next.js frontend
├── api/ # NestJS backend
packages/
├── db/ # Drizzle schema + migrations
├── shared/ # Shared types and utilities
├── config/ # Shared configurationSecurity & Multi-tenancy
Row Level Security (RLS) is the backbone of ForgeStack's multi-tenancy implementation. Every table with tenant data has RLS policies that filter rows based on the current session's tenant context. This happens at the database level, making it impossible for application bugs to leak data between tenants.
The RBAC system is built on top of this foundation. Permissions are scoped to tenants, and role assignments are verified on every request. The combination provides defense in depth—even if the application layer has a bug, the database layer prevents unauthorized access.
-- Every tenant-scoped table uses RLS
CREATE POLICY tenant_isolation ON projects
USING (tenant_id = current_setting('app.tenant_id')::uuid);
-- Application sets tenant context on each request
SET app.tenant_id = 'tenant-uuid-here';Developer Experience
A starter kit is only valuable if it's pleasant to work with. ForgeStack prioritizes DX through several mechanisms:
• Single command to spin up the entire stack • Hot reload across all applications • Type safety from database to frontend • Consistent code style via shared ESLint and Prettier configs • Pre-configured CI/CD pipelines
The goal is to feel like working in a mature codebase from day one, without the baggage of legacy decisions.
Testing & Quality
ForgeStack includes a comprehensive testing setup out of the box. Unit tests for business logic, integration tests for API endpoints, and the infrastructure for e2e tests. The test database uses the same RLS policies as production, ensuring tenant isolation is verified in tests.
Code quality is enforced via strict TypeScript configuration, ESLint rules, and Prettier formatting. The CI pipeline runs all checks on every PR, preventing quality regressions.
What ForgeStack Deliberately Does NOT Solve
I chose to keep ForgeStack focused on infrastructure, not product logic. This restraint is intentional.
• **No billing logic or pricing models**: Every SaaS has different pricing strategies. ForgeStack provides the tenant and plan primitives, but doesn't prescribe how you charge customers.
• **No product-specific workflows**: This isn't a CRM starter or an e-commerce template. It's infrastructure that works regardless of your domain.
• **No opinionated frontend abstractions**: The Next.js app is minimal by design. Your product's UI should reflect your product, not a starter kit's opinions.
By not solving these problems, ForgeStack remains adaptable across different SaaS domains without becoming rigid. I accepted the tradeoff of providing less out-of-the-box functionality in exchange for broader applicability.
Failure Modes Designed Against
I designed ForgeStack with specific failure scenarios in mind — these weren't afterthoughts.
• **Tenant data leakage**: The primary threat. RLS policies enforce isolation at the database level, making it structurally difficult to leak data between tenants. Even if application code has bugs, the database layer prevents cross-tenant access.
• **RBAC drift over time**: Permissions systems tend to accumulate cruft. ForgeStack's RBAC is designed to be auditable — every permission is explicit, and the schema makes it easy to query "who has access to what."
• **Schema evolution breaking isolation**: As the schema changes, RLS policies must evolve with it. ForgeStack's migration strategy requires RLS policies to be defined alongside table creation, making it harder to forget.
• **Performance degradation under multi-tenancy**: RLS policies add query overhead. I chose to accept this cost because the security guarantees are worth it for B2B SaaS. For products that hit scale limits, tenant sharding becomes the next evolution.
These weren't hypothetical concerns — they're patterns I've seen fail in production systems.
Tradeoffs
Every architecture involves tradeoffs. ForgeStack optimizes for:
• **Security over simplicity**: RLS adds complexity but provides strong guarantees • **Type safety over speed**: Strict TypeScript catches errors early but requires more upfront work • **Monorepo over microservices**: Simpler deployment and shared code, but tighter coupling
These tradeoffs make sense for most B2B SaaS products, but may not fit every use case.
What I'd Improve Next
• Add support for organization hierarchies (parent/child tenants) • Implement audit logging for compliance requirements • Add webhook infrastructure for integrations • Build admin tooling for tenant management • Add observability stack (metrics, traces, logs)