The most consequential SaaS architecture decision is not monolith vs microservices. It is the multi-tenancy model: shared database with tenant column, schema-per-tenant, or database-per-tenant. This single decision determines data isolation, performance ceiling, compliance capability, and how painful a migration becomes when you need to change it. Madgeek has built SaaS products using all three models, and the wrong choice caused the most expensive rewrites we have seen.
The reason this decision matters more than the monolith vs microservices debate: you can refactor a monolith into services incrementally. You cannot change your multi-tenancy model without touching every query, every migration, and every backup process in the system. It is the one decision that compounds in difficulty the longer you wait to get it right.
Which multi-tenancy model should you choose?
The three models exist on a spectrum of isolation vs operational simplicity. None is universally correct. The right choice depends on your compliance requirements, expected tenant count, and data volume distribution across tenants.
Factor | Shared DB (tenant column) | Schema-per-tenant | DB-per-tenant |
|---|---|---|---|
Build cost | Lowest | Moderate | Highest |
Data isolation | Application-level only | Schema-level (strong) | Complete (separate instances) |
Practical tenant limit | Thousands (with index tuning) | 100 to 1,000 per DB server | Limited by infrastructure budget |
Compliance suitability | Weak (data commingled) | Good (auditable separation) | Strongest (required for regulated industries) |
Migration difficulty | Simple (one migration, all tenants) | Moderate (run per schema) | Complex (run per database) |
Best for | High tenant count, similar data volumes, no compliance mandate | 100 to 1,000 tenants, enterprise clients who ask where their data lives | Regulated industries (healthcare, finance), tenants with wildly different data volumes |
The practical decision filter: if any customer will ever ask "where is my data stored?" during a sales call or security review, you need schema-per-tenant at minimum. If your customers operate in regulated industries (healthcare, financial services, government), start with database-per-tenant. The cost of retrofitting isolation is 5x to 10x higher than building it from the start.
When does the monolith actually make sense?
For SaaS products with fewer than 50,000 users and a team of fewer than 10 engineers, a well-structured monolith deploys faster, costs less to operate, and is significantly easier to debug than a microservices architecture. Rails, Laravel, Django, and Next.js all support monolithic SaaS products at this scale without performance problems.
The key phrase is "well-structured." A monolith is not a ball of mud. It has clear module boundaries, separated concerns (business logic does not live in controllers), and a test suite that catches regressions before deployment. The difference between a monolith that scales and one that becomes a rewrite target is internal discipline, not architecture pattern.
Microservices add operational complexity that small teams cannot absorb. Each service needs its own deployment pipeline, monitoring, log aggregation, and failure handling. A 5-person team running 12 microservices spends more time on infrastructure than on the product. Madgeek has advised SaaS founders to consolidate back into a monolith after microservices slowed their shipping speed to a crawl. In one case, the team went from deploying twice a week to deploying daily after the consolidation.
What triggers a move to microservices?
Team size alone is not the trigger. Traffic alone is not the trigger. The real trigger is when two parts of the system need to scale independently. If your API handles 10x more read traffic than your background job processing queue, those two concerns belong in separate services. If a change to the billing module keeps breaking the notification system because they share database tables, they need separate data stores and a message queue between them.
The second trigger is deployment coupling. When you cannot deploy one part of the application without risking another, the monolith has outgrown its structure. This shows up as: "We wanted to ship a billing fix but had to wait for the notification refactor to finish because they are in the same deploy pipeline." That is the signal to extract a service.
The correct approach is incremental extraction. Take the one component causing the most scaling or deployment pain and extract it into a service with a well-defined API boundary. Run it alongside the monolith. Extract the next component only when the first extraction is stable and the team has built the operational muscle (monitoring, deployment, failure handling) for distributed systems. Madgeek's SaaS development process follows this pattern because it reduces risk at every step.
Where does serverless fit in a SaaS architecture?
Serverless (AWS Lambda, Google Cloud Functions, Vercel Edge Functions) works well for specific workloads: background jobs like PDF generation and email sending, API endpoints with unpredictable traffic spikes, data processing pipelines that run on a schedule, and webhook handlers that sit idle 95% of the time.
Serverless does not work well for long-running processes (anything over 15 minutes), stateful operations (WebSocket connections, real-time collaboration), or anything sensitive to cold start latency (user-facing API responses where a 2-second delay on the first request is unacceptable). Using serverless as the entire architecture works for tools and utilities with low, bursty traffic. It does not work for full SaaS products with consistent user sessions and real-time requirements.
The pattern that works in production: a monolith or small set of services handles the core application, and serverless functions handle the peripheral workloads (PDF exports, image processing, scheduled reports, third-party webhook ingestion). This gives you the cost efficiency of serverless where it matters without forcing your entire application into a stateless execution model.
What are the three decisions you cannot change later?
Three architecture decisions become exponentially expensive to change after launch. Get these right in the first build.
First: the multi-tenancy model. Migrating from shared database to schema-per-tenant requires rewriting every database query, every migration script, every backup process, and every reporting pipeline. For a SaaS product with 500 tenants and 200 database tables, this is a 3 to 6 month project that ships zero new features while it runs. The SaaS development timeline accounts for this decision upfront so it never becomes a rewrite.
Second: the authentication architecture. Switching from a custom auth implementation to Auth0, or from Firebase Auth to a self-hosted solution, breaks every integration, every session management flow, every API token, and every webhook signature. Plan auth once. Use a system that handles your current needs and scales to your next 10x of users without a migration.
Third: the event system. A SaaS product built on synchronous CRUD operations (create a record, update a record, delete a record) works at small scale. At medium scale, you need asynchronous event handling: "when a deal closes, trigger invoice generation, notify the account manager, update the dashboard, and start the onboarding sequence." Retrofitting event sourcing or even a simple event bus into a CRUD application is a full rewrite of every state-changing operation. Build the event layer from day one, even if the first version only logs events without acting on them.
Written by
Abhijit Das
CEO
Building AI tools for businesses from legacy to new age SaaS startups
LinkedIn ↗Building something complex?
Start a project with Madgeek