Tenant isolation is the decision everything else follows from
Three isolation strategies exist: separate databases, a schema per tenant, or a shared schema with a tenant key. The trade is operational cost against isolation strength, and the honest answer is that most SaaS products should start on a shared schema and most enterprise deals eventually argue for more.
What matters is that the choice is explicit and enforced rather than implied by which queries somebody remembered to write. We make the tenant part of the data access path itself, so a query that forgets the tenant filter fails instead of returning someone else's rows. A mistake returns no data rather than another customer's data, and that difference is the whole game when an enterprise customer asks their auditor to look. Making the tenant's jurisdiction and data location part of that same path is multi-tenant SaaS development with per-tenant data residency, and where the product is still early MVP development for a first UAE release is usually the right first step.
Sharing a codebase does not mean sharing a database
Multi-tenancy is often confused with code reuse, and conflating them is where the real problem appears. A shared schema with strict access control is a legitimate cloud software architecture and is the right default. What is not legitimate is a shared schema where isolation depends on every developer remembering a filter in every query.
So we push tenant scoping into the data layer: row-level security, or an ORM and query builder that cannot express a tenant-unaware query. The cost is a small amount of up-front discipline. The benefit is that isolation no longer degrades as the team grows, which is the actual risk in a growing SaaS product.
Billing is a state machine, not a monthly job
Subscription billing looks simple until a customer upgrades mid-cycle, adds seats, applies a coupon from a sales deal, switches from monthly to annual, or fails a payment during a bank holiday. Each of those changes what is owed and when, and getting it wrong creates refund requests and a finance team that stops trusting the product.
We model billing as an explicit state machine: subscriptions, plan changes, proration, usage records, invoices, and payment attempts, with the rule that the source of truth is the subscription record and everything else is derived. That is what makes a revenue report trustworthy and what makes it possible to answer a customer question about their invoice without an engineer reconstructing history by hand.
Enterprise buyers ask about identity first
The question that most often decides whether a B2B deal progresses is not about the feature set. It is whether the product supports single sign-on (SSO), directory provisioning, and role mapping from the customer's own identity provider. Teams that treat this as a late feature often lose the deal on a requirement that takes weeks, not months, if it was designed for.
We build SAML and OIDC sign-in, SCIM provisioning, and role mapping as part of the core identity model rather than an enterprise bolt-on, with a permission model that is fine-grained enough to map onto how the customer's organisation is actually structured.
The public API is a product surface
If customers integrate, the public API is part of your product whether or not you designed it that way. We treat it as one: versioned contracts, generated documentation, a sandbox, a clear deprecation policy, and rate limits that behave predictably. An API that breaks customers without warning converts integration partners into support tickets.