Mastering Frappe Framework – Part 9: Building a SaaS Product with Frappe

Why Frappe is Perfect for SaaS

The Frappe Framework is already built for multi-tenancy, role-based permissions, and rapid UI generation — three things every SaaS product needs.

You can go from idea to MVP in weeks, not months.


1. Understanding Multi-Tenancy in Frappe

In SaaS, multiple customers (tenants) share the same app but have isolated data.

Frappe supports two models:

  1. Single-tenant per site – Each customer has their own Frappe site & database.
  2. Multi-tenant shared app – Multiple customers share one app but data separation is handled via permissions & domains.

Recommendation: Start with single-tenant for easy isolation; move to shared tenancy if you want lower hosting costs.


2. Setting Up Multi-Tenancy

Enable multi-tenancy in your bench:

bench config dns_multitenant on


Create a site for each tenant:

bench new-site client1.yourdomain.com
bench new-site client2.yourdomain.com


Install your app:

bench --site client1.yourdomain.com install-app myapp
bench --site client2.yourdomain.com install-app myapp

3. Subscription & Payment Integration

A. Adding a Subscription Model

  • Create a Subscription DocType:
    • Fields: Plan Name, Price, Billing Cycle, Start Date, End Date.
    • Link to Customer DocType.
  • Add a before_save hook to check active plan before granting access.

B. Payment Gateway Integration

Popular choices:

  • Razorpay (India)
  • Stripe (Global)
  • PayPal (Global)

Example with Razorpay:

import razorpay

client = razorpay.Client(auth=("KEY_ID", "KEY_SECRET"))
payment = client.order.create({
    "amount": 50000,  # Amount in paise
    "currency": "INR",
    "payment_capture": 1
})


You can expose this via a Custom API endpoint in Frappe.

4. Auto-Suspending Expired Subscriptions

Use a daily scheduler event:

def check_subscriptions():
    expired_users = frappe.get_all("Subscription", filters={"end_date": ["<", frappe.utils.nowdate()]})
    for sub in expired_users:
        # Disable user access
        frappe.db.set_value("User", sub.user, "enabled", 0)


Add in hooks.py:

scheduler_events = {
    "daily": ["myapp.api.check_subscriptions"]
}

5. Scaling Your SaaS

  • Horizontal Scaling – Multiple servers behind a load balancer.
  • Separate DB per tenant – Easier migrations & backups.
  • Redis Cache & Worker Tuning – Reduce response time.
  • Read Replicas for MariaDB – Handle heavy reporting loads.

6. SaaS Best Practices

✅ Automate backups for each tenant.

✅ Use SSL for all customer domains.

✅ Monitor app health (uptime, errors, database size).

✅ Plan for migrations when updating your app.


Key Takeaways from Part 9

  • How to set up multi-tenancy in Frappe.
  • Creating subscription plans & integrating payments.
  • Auto-suspending expired accounts.
  • Scaling strategies for long-term SaaS growth.

Next in Part 10

We’ll cover Frappe Advanced Customization:

  • Client & server scripts
  • Webhooks
  • API rate limiting
  • Background jobs & workers

Leave a Reply