Multi-Tenant Compliance SaaS at 400-Endpoint Scale
A vendor-risk and compliance platform: tenant isolation with EF Core global query filters, CQRS across 54 feature modules, multi-IdP SSO, and Stripe subscription billing.
- Role:
- Architect and top contributor (~45% of 3,240 commits); lead a 6-developer team
- Period:
- 2025 – 2026, Brain Station 23
- .NET 8
- Next.js 15
- React 19
- PostgreSQL
- EF Core
- CQRS/MediatR
- Stripe
- SignalR
- AWS ECS Fargate
Context
TPSaaS helps companies manage vendor security risk: supplier onboarding, security assessments, evidence review, risk registers, audits, remediation, and certification. Every customer is a tenant with its own users, data, and subscription plan, so isolation failures are existential, not cosmetic.
Architecture
Key decisions
Tenancy enforced in the data layer. Tenant scoping lives in EF Core global query filters plus middleware that resolves the tenant before any handler runs. Developers cannot forget a WHERE TenantId = …: the filter applies unless explicitly and visibly disabled, which code review treats as a red flag.
CQRS kept honest at scale. 342 handlers across 54 modules stay navigable because each module owns its commands, queries, and validation. No shared god-services. New features follow a template, which is what makes a 6-developer team productive in parallel without merge wars.
Identity is pluggable. Enterprise customers bring their own IdP: the platform speaks OIDC to Azure AD, Okta, Auth0, and others, layered under a role model that separates platform administrators from tenant roles.
Billing with webhooks, not polling. Stripe subscriptions (including enterprise plans and quotas) sync through idempotent webhook processing; BitSight security ratings integrate with encrypted tokens and full API audit logging.
Results
The platform runs on AWS ECS Fargate with RDS PostgreSQL, S3, Secrets Manager, and ElastiCache across development, UAT, and production environments; 13 Hangfire recurring jobs handle assessment reminders, syncs, and digests. In-app SignalR notifications pair with SES email delivery including bounce tracking. I also wrote the pandas + psycopg2 ETL that seeded the question bank: tiered fuzzy matching that maps business-owner questions to conditional vendor follow-ups from questionnaire spreadsheets.
What I'd do differently
Introduce integration-test coverage per module earlier. The CQRS template made features fast to add; test scaffolding lagged behind it, and backfilling coverage is slower than growing it alongside.