A multi-tenant SaaS is mostly five decisions made early. Get them right and the build is fast. Get them wrong and you rewrite at the worst time. This is how we scope a Web App for a fixed price and still ship something that holds up.
Our Web App work is fixed at $6K-$25K, delivered in 3-5+ months. That window only exists because we refuse to invent. We pick boring tools and decide the hard things up front. Here are the calls that matter.
Tenant isolation: one database, scoped rows
Start with a shared database and a `tenant_id` on every table. Not a database per tenant. Not a schema per tenant. One Postgres instance, row-level scoping, an index on `tenant_id` everywhere it matters.
The failure mode is a query that forgets the tenant filter. One person's data leaks into another's account. So we enforce it below the application code, with row-level security or a query layer that refuses an unscoped read. The check lives in one place, not in 200 handlers.
Database-per-tenant feels safer and costs you everything. Migrations multiply. Connection pools sprawl. Your $25K budget evaporates into ops work nobody sees. Shared schema with hard scoping carries a SaaS to its first few thousand tenants. You move later, with revenue, if you ever need to.
Auth: buy it, do not build it
Authentication is not where you spend the budget. Use Cognito, or Clerk, or WorkOS. The build cost of rolling your own is real, and the maintenance cost is worse.
The decision that actually matters is the tenant model inside auth. Is a user in exactly one tenant, or many? Pick before you write a line. We default to one user, one tenant, because it covers most SMB cases and keeps the token simple. The tenant ID rides in the session and gets checked on every request.
Background work: a queue, not a cron hack
Anything slow goes on a queue. Email, exports, report generation, anything calling another API. SQS plus a worker, or a managed equivalent. The web request returns fast and the work happens behind it.
Skip this and your first heavy customer times out a request and assumes the product is broken. The fix mid-flight is painful because synchronous code has to be torn apart. A queue from day one costs an afternoon. We build it in.
Per-tenant config without a config nightmare
Every SaaS grows tenant-specific settings. Feature flags, limits, branding, billing tier. Keep it as data, in a `tenant_settings` row, not as branches in code. Reading a flag is a lookup, never a deploy.
The trap is hardcoding a customer's special case into a handler. Do that twice and the codebase forks in your head. Data-driven config means a new tenant is a row, and onboarding does not touch the build.
Billing: wire the boundary, defer the rest
Use Stripe and put the integration at the tenant boundary. A tenant maps to a customer and a subscription. That is the wiring that is expensive to add later, because it touches every gate in the app.
You do not need usage metering or seat proration on day one. Most teams never use them. Build the subscription link, gate features off the tier in `tenant_settings`, and add complexity when a real plan demands it. Not before.
Why fixed price works here
These five calls are why we can quote a Web App as fixed price, every time. There is no discovery rabbit hole because the architecture is decided, not discovered. We have made these choices across 17 production products, 10 of them in our first 7 months, as a 2-person team, one of us an ex-AWS Federal Solutions Architect with 18 cloud certifications.
You own the code at the end. We hand it over and exit. No lock-in, no retainer you did not ask for. If the build needs a RAG Chatbot or a heavier integration, we scope that separately, also fixed.
The mistake we see most is over-building tenancy before there are tenants. Database-per-tenant, a custom auth service, a metering pipeline, all for a product with zero paying customers. Ship the boring version. Earn the complexity.
If you are weighing a multi-tenant build and want a straight answer on scope, book a call. Thirty minutes, free, no deck. We will tell you what these decisions cost in your case.