vincent15000's avatar

Migrate an application from mono-user to multi-user configuration

Hello,

Some year ago, I have developed a Laravel application for a client and this application is used by only one user.

Today my client wants to share her application with another user and both users will have their own datas and are will be allowed to access only his own datas.

Anyway the application will be likely a tenant application.

What's the best way to migrate the application from a mono-user to a multi-user configuration ?

I have thought about some solutions.

Create a new database for the new user

I would have a database only with the users and the common datas between all users. And each user would have his own database for all his own datas. For each user I would have the add database name in a configurations table attached to the users table. Very convenient to export all datas from the database if needed. This way I don't have to add any scope to access the datas, but it would be necessary to manage the migrations in each database.

Keep a unique database

Each table woud have an organisation_id field and models would have scopes to filter the datas. It seems to be easier to develop, but this will need a lot modifications in the code and in the database (foreign keys, scopes, ...).

Another way ?

If you have other ideas, don't hesitate to share them with me ;).

What solution do you suggest me ?

Thanks a lot for your help.

V

0 likes
6 replies
LaryAI's avatar
Level 58

Hello V,

Migrating your Laravel application from a mono-user to a multi-user configuration is a common requirement as applications grow and evolve. Both of the solutions you've considered have their own pros and cons. Let's discuss them briefly and then I'll suggest a path forward.

Create a new database for the new user

This approach is often referred to as a multi-database or multi-tenant architecture. It's great for data isolation and can be beneficial if you expect to scale to a large number of users, each with significant amounts of data. However, it does add complexity to your application, especially when it comes to database migrations, connection management, and potentially increased infrastructure costs.

Keep a unique database

Adding an organisation_id to each table and using model scopes is a more traditional approach to multi-tenancy within a single database. It's simpler to manage in terms of infrastructure and can be more cost-effective. However, it requires careful attention to ensure data isolation and security, as all data is stored in the same database.

Suggested Solution

Given the information provided, I would suggest starting with the single database approach. This is because it's generally easier to implement and manage, especially if you're only adding a small number of users. Here's how you can proceed:

  1. Add organisation_id to your tables: You'll need to modify your database schema to include an organisation_id column on all tables that contain user-specific data.

  2. Update your models: Add a global scope to your models to automatically filter queries by the current user's organisation_id.

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class YourModel extends Model
{
    protected static function boot()
    {
        parent::boot();

        static::addGlobalScope('organisation', function (Builder $builder) {
            $builder->where('organisation_id', auth()->user()->organisation_id);
        });
    }
}
  1. Update your foreign keys: Ensure that your foreign keys and relationships are updated to reflect the multi-user setup.

  2. Migrate existing data: You'll need to assign an organisation_id to all existing data to associate it with the current user.

  3. Update your application logic: Go through your application logic to ensure that all data creation and modification actions are scoped to the current user's organisation_id.

  4. Implement robust access controls: Make sure that your application has proper authentication and authorization checks in place to prevent users from accessing data that doesn't belong to their organization.

  5. Test thoroughly: Before deploying these changes, make sure to thoroughly test your application to ensure that the data isolation is working as expected and that there are no security holes.

This approach will allow you to transition to a multi-user setup with minimal changes to your infrastructure and without the overhead of managing multiple databases. If, in the future, you find that this setup is not scalable enough or you need stronger data isolation, you can consider moving to a multi-database architecture.

Remember to backup your database before making any schema changes and to test your changes in a staging environment before deploying to production.

Good luck with your migration!

1 like
vincent15000's avatar

@LaryAI Is it really necessary to add an organisation_id field to all tables that contain user-specific data ?

I mean ... for example if I have a recipes table, an ingredients table a steps table. Each recipe has many ingredients and many steps.

For this example, is it necessary to add an organisation_id to the ingredients and steps tables, given that ingredients and steps are attached to the recipes ? Given this context, is it sufficient to add an organisation_id to the recipes table ?

I know that adding an organisation_id to the recipes table can work, but is there any contradictions related to security reasons or to data isolation ?

1 like
martinbean's avatar
Level 80

@vincent15000 It completely depends on if you anticipating ever viewing both users’ data, i.e. for reporting or in some sort of “super user” context. If the answer is “yes” then just keep the data in the same database and add some sort of foreign key designating the owner (i.e. a user_id column) and only show records for the currently authenticated user.

1 like
vincent15000's avatar

@martinbean The application is designed properly and it's not difficult to add a superuser that could access only certain datas.

Hmmm ... What about the last question I asked for ? (see my last comment yesterday)

jlrdw's avatar

@vincent15000 work out authorization, who can or cannot do something.

I generally design with paper and pencil first, so I can see an overview. And having it written helps me not leave out something.

1 like
Ben Taylor's avatar

I personally have worked with both strategies, and have found them both good in different scenarios. A few things to ponder regarding the second approach. Can users belong to multiple organisations? If so, will they have different roles in each organisation? Getting these kind of relationships right from the start will help a lot as you migrate toward multitenancy.

1 like

Please or to participate in this conversation.