Multi-tenant SaaS
Task-Flow
A complete multi-tenant SaaS: tenant-isolated workspaces, Stripe subscription billing, real-time Kanban and a Redis-backed job queue.
The problem
Small teams outgrow a shared spreadsheet quickly, but the tools that replace it are either too heavy or priced per seat in a way that punishes growth. I wanted to build the full thing rather than a demo: a product that a real team could sign up for, pay for, and use together in real time.
That meant solving the three things a task board demo usually skips: tenant isolation, billing and real-time state.
What I built
- Multi-tenant workspaces where every record is scoped to a tenant at the database level, so one workspace can never read another's data.
- Role-based access control with three tiers, Admin, Manager and Member, enforced at the API layer and reflected in the UI so people never see actions they cannot take.
- Stripe subscription billing with webhook handling, so plan changes, renewals and failed payments update the account state without manual intervention.
- A drag-and-drop Kanban board that broadcasts every move over Socket.io, so a card dragged on one screen lands on everyone else's board without a refresh.
- A BullMQ and Redis job queue for email notifications, assignment alerts and scheduled reminders, decoupled from the request cycle.
Architecture decisions
Isolation at the data layer, not the query layer
Tenant scoping lives in the schema and the data access layer rather than being remembered at each call site. A missed filter is the classic multi-tenant leak, so the safe path is the default path.
RBAC enforced twice, on purpose
Permissions are checked on the API because that is the boundary that matters, and mirrored in the UI because hiding an action a user cannot perform is a better experience than showing them an error.
Webhooks as the source of truth for billing
The client never decides whether a subscription is active. Stripe webhooks drive the account state, which keeps billing correct even when a user closes the tab mid-checkout.
Queues for anything that can wait
Email and reminders run through BullMQ on Redis. The API returns as soon as the write is durable, and the slow work happens out of band where a failure can be retried rather than surfaced to the user.
Hard parts
- Keeping the real-time board consistent. Drag and drop is optimistic by nature, so the UI has to move immediately and still agree with the server and with every other connected client afterwards.
- Making billing state and permission state agree. A downgrade has to change what people can do, immediately, and without locking anyone out of data they already own.
- Testing the tenant boundary. The interesting bugs in multi-tenant systems are the ones you only see with two tenants and a shared cache in play.
Outcome
Task-Flow is the project I point recruiters and clients to first, because it covers the full surface of a commercial SaaS product: authentication, tenancy, permissions, payments, real-time collaboration and background processing, deployed and running rather than described in a README.