Building a SaaS from Scratch: Architecture, Multi-Tenancy and Billing

A SaaS differs from an ordinary web app not in its interface but in the fact that a single codebase and a single infrastructure serve many independent customers at once. Every key engineering decision flows from this: how to isolate tenant data, how to bill subscriptions, how to meter usage, and how to grow without rewriting the system every six months. Below is a practical breakdown with no marketing fluff.
Multi-tenancy: three models of data isolation
Multi-tenancy is the way you store and separate the data of different customers within one shared system. The chosen model dictates infrastructure cost, development speed and the level of isolation. In practice, three approaches are used.
- Shared schema, shared tenant_id column. All tenants live in the same tables, with rows tagged by customer ID. Cheap and easy to scale, but it demands discipline: every query must filter by tenant_id.
- Schema per tenant. One database, but each customer gets its own schema. Better isolation and easier per-customer backups, but migrations get harder across hundreds of schemas.
- Database per tenant. Maximum isolation, suited to large enterprise and regulated customers (banks, healthcare). Expensive to operate and hard to automate.
Billing and subscriptions: the core you cannot underestimate
Billing looks simple right up until your first production launch. In reality, subscription logic is a finite state machine: trial, active, past_due, grace period, suspended, canceled, refunded. Each state affects feature access and invoicing. If you bury this in scattered if-statements across the codebase, maintenance becomes hell.
Key billing components:
- Catalog of plans and features — what a plan includes, what the limits are, which features are enabled.
- Subscriptions — the "tenant + plan + period + status" binding with a change history.
- Invoice logic — generating invoices and proration on mid-cycle upgrades and downgrades.
- Payment layer — integration with providers and handling of payment webhooks.
- Reconciliation — matching subscription status against actual payments. Never treat a single counter as the truth.
A word on Uzbek market realities: international Stripe/Paddle are not directly usable here for accepting local payments. The working approach is integrating with local providers: Payme, Click, Uzum. Each has its own webhook model, signature verification and refund requirements. Build a payment-gateway abstraction from day one so that adding a second and third provider does not break the subscription core.
Pricing: how to package value
The pricing model is a product decision with a direct impact on revenue. The main schemes:
A few rules proven in practice:
- Tie price to a metric that grows with the value delivered to the customer (headcount, processed orders, devices), not to technical load.
- Make limits soft: a warning and a grace period beat an abrupt cutoff that breeds churn.
- Store pricing as data, not as code. A new plan or promo should not require a release.
For the Uzbek market, prices are usually quoted in soʻm, and the corporate segment expects contracts and electronic invoices (ESF). If you sell to legal entities, billing must be able to export data for accounting, not just charge a card.
Scaling: measure first, split later
Premature complexity is a common disease. Microservices, Kubernetes and sharding at the 50-customer stage usually do more harm than good. The right path is to grow along bottlenecks, guided by metrics.
- Vertically and via cache at the start: database indexes, caching hot queries, a connection pool (PgBouncer for PostgreSQL).
- Horizontally for the stateless layer: several app instances behind a load balancer, background jobs in queues.
- Sharding by tenant_id — only when a single database genuinely stops coping. The good news: with proper multi-tenancy, tenant_id is already a natural sharding key.
- Regional proximity: for an Uzbek audience, latency to servers in the EU/US is noticeable. Local hosting or a read replica closer to the user markedly improves dashboard responsiveness.
Metrics: what to measure to stay in control
A SaaS without metrics is flying blind. The minimum set that should be computed automatically:
- MRR / ARR — recurring monthly and annual revenue, the foundation of all subscription economics.
- Churn — customer churn and revenue churn (revenue churn matters more than logos).
- LTV and CAC — customer lifetime value against acquisition cost; a healthy LTV/CAC ratio is 3 or higher.
- Activation — the share of customers who reach the key action (first real value), not just those who signed up.
- Expansion / NRR — growing revenue within existing customers through upgrades and extra seats.
Technically, build metrics on an event log rather than the current snapshot of tables: that way you can reconstruct history and won't lose facts when the schema changes.
Conclusion
A viable SaaS is a bundle of four decisions made deliberately at the start: a multi-tenancy model with isolation enforced at the infrastructure level, billing built as a state machine with server-side payment reconciliation, pricing stored as data, and metrics built on events. Everything else (microservices, sharding, multi-region) is added as you grow and only against a proven bottleneck. If you plan to launch a SaaS in the Uzbek market with local payment providers and corporate reporting, the OneDev team is ready to discuss your product's architecture and help you avoid costly mistakes before your first production release.
Which multi-tenancy model should I choose at launch?
Can I use Stripe in Uzbekistan?
When do I need database sharding?
Why can't I trust the payment form's response?
Which SaaS metrics should I track first?
How much does launching a SaaS MVP cost?
Need a similar system or want to discuss your project?
Describe the task — we will propose architecture, technical approach and a work plan. A short call is usually enough to get started.
Discuss project