cd /news/cloud-computing/multi-tenant-saas-for-30-mo-wildcard… · home topics cloud-computing article
[ARTICLE · art-12434] src=dev.to ↗ pub= topic=cloud-computing verified=true sentiment=↑ positive

Multi-tenant SaaS for $30/mo: wildcard SSL + nginx vhost generator + Flask routing

This article describes a cost-effective multi-tenant SaaS architecture that runs over 50 tenants on a single $30/month VPS using a wildcard SSL certificate, an nginx regex-based virtual host generator, and a Flask routing system that scopes data by partner slug. The setup eliminates the need for per-tenant configuration or Kubernetes by automatically provisioning new partners via a webhook, with the only write operation being a database row insertion. The author argues that many developers over-engineer with microservices and managed cloud services when a simple monolith with SQLite is sufficient for early-stage growth.

read3 min views23 publishedMay 23, 2026

Every "build a SaaS" tutorial reaches for Kubernetes, managed Postgres, and three cloud services before the first user signs up. You don't need that. Here's a multi-tenant setup that runs 50+ tenants on subdomains, on one $30/mo VPS.

The requirement #

White-label partnership program. Each partner gets a storefront at partner-{slug}.guardlabs.online

with our catalog, their referral IDs baked in. New partner → automatic provisioning after payment webhook.

Phase 1 (0-50 tenants): wildcard SSL + nginx + Flask #

Wildcard SSL via Let's Encrypt — one cert covers *.guardlabs.online

:

certbot certonly --manual --preferred-challenges dns \
  -d "*.guardlabs.online" -d "guardlabs.online"

(DNS-01 challenge — add the TXT record your DNS provider, certbot validates.)

nginx server block routing by $host

:

server {
    listen 443 ssl;
    server_name ~^partner-(?<partner_slug>.+)\.guardlabs\.online$;
    ssl_certificate     /etc/letsencrypt/live/guardlabs.online/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/guardlabs.online/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8090;
        proxy_set_header Host $host;
        proxy_set_header X-Partner-Slug $partner_slug;
    }
}

Flask reads the header, scopes everything to that partner:

@app.before_request
def load_partner():
    slug = request.headers.get("X-Partner-Slug")
    if slug:
        g.partner = db.execute(
            "SELECT * FROM partners WHERE slug=?", (slug,)
        ).fetchone()
        if not g.partner:
            abort(404)

@app.route("/")
def storefront():
    products = get_catalog()  # global catalog
    return render_template("store.html",
        products=products,
        ref_id=g.partner["ref_id"],  # injected into every buy link
        partner_brand=g.partner["brand_name"])

Provisioning on webhook — when Whop sends "new subscription":

@app.route("/webhook/whop", methods=["POST"])
def whop_webhook():
    event = verify_and_parse(request)
    if event["type"] == "subscription.created":
        slug = slugify(event["user"]["username"])
        db.execute("INSERT INTO partners (slug, ref_id, ...) VALUES (...)")
    return "", 200

That's the trick: the regex server_name means zero new nginx config per partner. Wildcard SSL means zero new certs. The DB row is the only write.

Capacity: one VPS, monolith Flask, SQLite. ~50 partners with 10 concurrent users each = 500 concurrent. A $30/mo Hetzner CCX handles that without breathing hard.

Phase 2 (50-200 tenants): per-tenant SQLite #

Move from shared DB to /data/partners/{partner_id}/store.db

. Flask switches connection by X-Partner-Slug

. ~16 hours of refactor. SQLite holds 10k+ rows per file fine; 200 partners × 10k = 2M rows total, no problem.

Phase 3 (200-500+): PostgreSQL schema-per-tenant #

Now you migrate. One Postgres, schema per partner. 40 hours. Now you might want Kubernetes. Not before.

The point #

I provisioned this whole thing in about 8 hours. Total infra budget for 12 months: under $5K. The "you need microservices and managed everything" advice is for companies with funding and a platform team. For a solo founder: nginx regex + wildcard SSL + a Flask before_request

hook gets you to 50 paying tenants.

Try it #

The partnership it powers: 7-day free trial, no card, $29/mo. guardlabs.online/partner. And the bot the whole thing grew out of: Phantom paper-trader (384 trades, 57% win-rate, public).

Question #

What's your "we over-engineered this" story? When did you reach for Kubernetes before you needed it?

Code and full launch log in public. Following along.

📥 Free chapter — 20 no-budget growth tactics

This launch log runs on a playbook. If you want the actual tactics — Google-ecosystem hacks, trend-jacking, the HARO authority play — grab two free sections of the Blueprint. No PDF wall, no login: it opens in your browser. Real numbers, real code, no fluff.

── more in #cloud-computing 4 stories · sorted by recency
── more on @let's encrypt 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/multi-tenant-saas-fo…] indexed:0 read:3min 2026-05-23 ·