question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Multi-tenant architecture using schema.

See original GitHub issue

Issue type:

[X] question [ ] bug report [ ] feature request [ ] documentation issue

Database system/driver:

[ ] cordova [ ] mongodb [ ] mssql [ ] mysql / mariadb [ ] oracle [X] postgres [ ] cockroachdb [ ] sqlite [ ] sqljs [ ] react-native [ ] expo

TypeORM version:

[X] latest [ ] @next [ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

We are using TypeORM trough NestJS framework, currently trying to resolve issue with multi-tenancy. Currently what we see for PostgreSQL there are 3 different options to handle multi-tenant architecture in Single server/cluster mode.

  1. Single server/cluster, single database, tenant column in each table.
  2. Single server/cluster, single database, multi schema per customer.
  3. Single server/cluster, multi database per customer.

While the 1st one could work the best, first of all for some security reasons we cannot go with it, especially when data grow over time the query performance will drop down, the 3rd one would require opening new connection for each of the database, as Google Cloud SQL (ref. https://cloud.google.com/sql/docs/quotas) has limits with max concurrent connections at time, this one could make some issues also.

We decided that we will go with option 2, so for each customer we have scripts which copy all tables from template schema into newly created schema.

E.g. customer1, customer2, customer3, customer4, customer5… so all tables and entities looks exactly the same as in the others (during schema change we are using migration tool/custom script to update schema in each customer schema).

Currently as far as we get there is no multi-tenant supported in TypeORM within Schemas (there is an option but it is using QueryBuilder on top, but we want to use all functionality of TypeORM which saves us a lot of time with development ref. https://stackoverflow.com/questions/57459643/typeorm-dynamically-set-database-schema-for-entitymanager-or-repositories-at-ru) in some sort of dynamic way, there are however Entities which we can mark as specific schema, but having this for 100+ customers in one database would be overkill to add new classes per every customer that is coming to our software (ref. https://github.com/typeorm/typeorm/issues/1019).

What would be the best option to go trough TypeORM in dynamic schema?

E.g.

import { Injectable, Inject } from '@nestjs/common';
import { Repository } from 'typeorm';
import { Photo } from './photo.entity';

@Injectable()
export class PhotoService {
  constructor(
    @Inject('PHOTO_REPOSITORY')
    private readonly photoRepository: Repository<Photo>,
  ) {}

  async findAll(): Promise<Photo[]> {
    return await this.photoRepository.useSchema('customer1').find();
  }
}

While the .useSchema could basically do query schema based like this:

SELECT * FROM customer1.photoRepository LIMIT 1;

I see there might be one workaround to basically create copy of tables with different prefix, but while PostgreSQL has schema supported i don’t think this is an option. Having multiple connections in configuration using createConnections isn’t option also, as the customer’s instances can be created on fly.

There is also another option but it is on the database level to set search schema per user on the database level, but we want to avoid any miss-configuration there (it also require to create multiple connections at the init of an app while it has to be dynamic, this is not an option too).

ALTER USER customer1 SET search_path = customer1;

Kind request to provide some help or examples in this area.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:43
  • Comments:17 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
wintertime-inccommented, Nov 1, 2020

@KleinMaximus This is dependent on your backend and architecture and how you handle it.

3reactions
wintertime-inccommented, Oct 10, 2019

I make it working with NestJS middleware which manages the connections. Before each request I am validating if connection is opened in “Connections Manager” if not, opens it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Your Guide To Schema-based, Multi-Tenant Systems and ...
In this type of multi-tenancy, we create multiple schemas in the same database to provide data isolation to the tenants. At runtime, depending ......
Read more >
Multi-tenant Application Database Design | by Blake Howe
Schema-based multitenancy — A tenant has its own database schema with the tenant identifier to facilitate data isolation. This can be ...
Read more >
A beginner's guide to database multitenancy - Vlad Mihalcea
Learn various multitetancy strategies when using a relational database system like catalog, schema or table-based tenant isolation patterns.
Read more >
Multi-tenant SaaS patterns - Azure SQL Database
The schema of a multi-tenant database must have one or more tenant identifier columns so that the data from any given tenant can...
Read more >
5 Tips To Design For Multi-Tenancy Architecture
In order to represent different use cases for different users or tenants, multi-tenant architectures are designed to be reconfigurable and flexible along ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found