Sudharsan GS

Jul 01, 2026 • 4 min read

My SaaS runs a multi-tenant ERP on $20/month infrastructure

A practical breakdown of how FactoStack runs a multi-tenant manufacturing ERP for paying customers on roughly $20/month.

My SaaS runs a multi-tenant ERP on $20/month infrastructure

I'm building FactoStack, a manufacturing ERP for Indian MSMEs. It already has paying customers, live production data, and actual businesses depending on it every day.

The interesting part is that the whole setup is still extremely lean. I’m not doing anything clever for the sake of it. I’ve just tried to keep the architecture boring, cheap, and reliable enough for the current stage.

Here’s the honest breakdown.

The stack

  • Backend: NestJS (TypeScript), with modules split by domain like inventory, production, compliance, and payroll

  • Frontend: React + TanStack Router + TanStack Query, shipped as a static build and served through Nginx

  • Database: Amazon Lightsail Managed PostgreSQL, separate from the app instance with automated backups

  • API hosting: Amazon Lightsail 512MB instance running NestJS behind Nginx

  • Admin app: React + TanStack Router, deployed on Cloudflare Pages

  • Marketing website: Next.js, also on Cloudflare Pages

  • Email: Nodemailer

  • Payments: Razorpay, mainly because it fits Indian billing, UPI, and GST invoicing cleanly

  • Auth: JWT with tenant-aware access and feature flags

  • Analytics: PostHog free tier

  • Alerting: Telegram bot for demo bookings, signups, and onboarding events

Total infra spend is roughly $20/month right now. The admin app and marketing site are effectively free on Cloudflare Pages, so almost all of the paid cost is just the app box and managed Postgres.

Why Lightsail over EC2 or Railway

Three simple reasons:

  1. Predictable flat pricing. I don’t want billing surprises while the product is still early.

  2. Managed Postgres removes a category of operational work I don’t want to own yet.

  3. A 512MB box is enough for this stage. NestJS + Nginx idles at around 180MB RAM, so I still have room without paying for headroom I’m not using.

I’ll upgrade when usage or revenue justifies it, not because a startup architecture template says I should.

Why Cloudflare Pages for the admin app and website

The admin app is an internal tool for creating tenants, managing users, and toggling features. It’s a static frontend, so there’s no reason to keep it on the same box as the API.

The marketing site is the same story. Static output, CDN distribution, free hosting. Separating both from the core app keeps deploys safer too. A marketing site change should never be able to affect production API uptime.

The multi-tenant setup

I’m not running a separate database per customer. There’s a single Postgres instance, and every core table carries a tenant_id. Tenant context is injected at the request layer and enforced through the application.

For an early-stage ERP, this has been the pragmatic choice:

  • One migration path for everyone

  • Straightforward debugging and support

  • Flat infrastructure costs as new customers come in

  • Faster shipping because I’m not maintaining tenant-specific infra

Will this be the forever architecture? Probably not. But it’s the right one for the current stage, and that matters more.

Feature flags are doing real work

Every major module is controlled through flags tied to the tenant record. That includes things like HRMS, e-invoicing, production tracking, and food-processing-specific workflows.

When I onboard a customer on a specific plan, I just enable the right flags from the admin app. No code changes, no separate deployments, no branching logic at the infra level.

That matters because my customers are not identical. A food processing customer paying ₹2,999/month may need raw material traceability and batch tracking. A compliance-only customer paying ₹2,990/year may only need GST tooling. Same product, different surface area.

What this architecture optimises for

It optimises for shipping speed, low fixed cost, and operational simplicity.

That means a few deliberate trade-offs:

  • I’d rather have one well-understood server than a more distributed setup I barely need

  • I’d rather rely on managed database backups than spend time pretending I enjoy database operations

  • I’d rather add complexity after repeated demand, not before the first serious scale problem

There’s enough monitoring to know when something is wrong, enough isolation to keep things manageable, and enough flexibility to support multiple customer types. That is the bar I care about right now.

What I’d do differently

I used to overthink infrastructure. Before launch, I spent far too much time reading about containers, orchestration, and multi-region setups. None of that was the bottleneck.

The real bottleneck was always simpler: can a customer log in, complete work, and trust the product tomorrow morning?

Running on a small VM also forced better discipline. Fewer wasteful queries. Less dependency bloat. More attention to what actually runs in production. Constraints helped the codebase.

The point

You do not need a stack full of trendy services to run a real B2B SaaS. You need a setup you understand, can afford, and can recover when something breaks.

For me, that currently means NestJS, React, a small Lightsail instance, managed Postgres, and Cloudflare Pages.

FactoStack’s lowest plan starts at ₹999/month. Infrastructure is roughly $20/month. That math is completely fine at this stage, and it keeps the pressure where it belongs: on building something customers will keep paying for.

Join Sudharsan on Peerlist!

Join amazing folks like Sudharsan and thousands of other builders on Peerlist.

peerlist.io/

It’s available... this username is available! 😃

Claim your username before it's too late!

This username is already taken, you’re a little late.😐

0

1

0