SaaS application design

ASP.NET, News, PHP, Tutorials

SaaS applications, also known as multi-tenant applications, are very popular these days. A single instance of the software is available to multiple customers/tenants. Each tenant’s data is isolated and remains invisible to other tenants. All tenant databases have the same structure. The data is different, of course.

There are multiple ways to design and implement this kind of application in PHPRunner or ASPRunner.NET. You can get away using a single data to host all customers’ data but using a dedicated database for each customer is easier and more reliable. In this article, we’ll show the easiest way to build such an app.

You can see that we have a common saasdb database here and multiple identical client databases. We only need to add to the project one of those client databases, database1 one in our example.

Common saasdb database only contains a single table named users.

We will select this table as a login table on the Security screen. Based on the username we redirect users to their database. We would only need to add two lines of code to make this happen. Things will be slightly different in PHPRunner and ASPRunner.NET.


1. AfterSuccessfulLogin event

$_SESSION["dbname"] = $data["database"];

Based on who is logged in we save database name in the session variable.

2. Server Database Connection

Proceed to the Output Directory screen, add a new Server Database Connection for the second database connection (database1) and modify the line where we specify the database name. This example is for MySQL. The point is to use $_SESSION[“dbname”] instead of the hardcoded database name.



1. AfterSuccessfulLogin event


2. BeforeConnect event

.NET applications are compiled before they can be deployed meaning that we cannot use any code in a new Server Database Connection. For this specific reason, we have added BeforeConnect event in ASPRunner.NET v10.3.

This is how default connection string looks (as shown in the event Description):

GlobalVars.ConnectionStrings["database1_at_localhost"] = "Server=localhost;Database=database1;User Id=root;Password=";

This is how we need to change it to grab database name from the session variable:

GlobalVars.ConnectionStrings["database1_at_localhost"] = 
String.Format("Server=localhost;Database={0};User Id=root;Password=", XSession.Session["database"]);

This is it. If you logon as user1 now you will see two records in the Customers table.

And if you logon as user2 you will see three records in the same table, because we are connected to database2 now.

Of course, creating a fully-featured SaaS application takes more than two lines of code. You need to take care of user registration, create new databases on the fly, upgrade all databases when database structure changes, maybe add the billing part etc. But this article should definitely help you get started.

9 thoughts on “SaaS application design

  1. That looks great. Have you built the next parts like user registration, create new databases on the fly, upgrade all databases when database structure changes, maybe add the billing part etc? Thanks

  2. Hi there. Thanks you for such a good on PHPRunner.

    I won er if we could do this but with different options.

    Instead of username, can we so it on base of different critéria such ás years (database based on year, not username). The same user can access different data, depende on which year selected before Login.

    Thank you for this.

  3. Can the application be deployed in a shared web hosting environment? Or only in dedicated server where database user with full privileges will be required in order to duplicate database when new user signs up.

  4. Hi, can this be done in phprunner 10.7 using database api? Could you please give tutorial about how to use database api with mysql.
    Thank you

  5. PHPRunner continues to surprise us (positively).

    Heads up, in practice, this seems to need an extra step for PHPRunner (and probably ASPRunnerPro too).

    (my scenario, a SQLite database)

    Step 0 > Login Page: Before Process

    For the login page to be successful in querying “a” database to obtain the user database, it needs to have a default database connection set to start with.
    Without it, it cannot query the database to work out, which “database” the user should be redirected to.

    Warning (probably an obvious one)
    This means that you ought to have one of your database, which contains in the user table, the list of ALL users and logins for every single tenant.

  6. Slight change to the design mentioned above.

    Just create a central “admin” style database with your user logins.

    And use that as your default database in the before process event for the login.php page.

    That will save you from having to replicate the sec_users table in all of the tenant databases (since PhpRunner.Net accepts multiple database connections).

Leave a Reply

Your email address will not be published. Required fields are marked *