Database Design – Multi-Tenant Database Design Strategies

database-designdesignmultitenancysql server

My boss is currently working on a database design for a multi-tenant capable ERP/CRM system, which will have a Sql Server backend.

Some key points of the design:

  • A server instance will host a "shared" database (unique model), plus one database per company (same model)
  • The "shared" database have tables like contacts, users, etc. that will be referred to by other company databases.
  • The "shared" database have triggers that will check if its data can safely be deleted (if it's used by any company, the DELETE operation must fail)
  • If, for security concerns, a company must NOT use shareable information, it must be set up on its own server instance, with its own "shared" database that will, in fact, be used only by that company.

And here's an implementation example for a system:

SERVER INSTANCE 1:

  • Shared DB
  • ACME
  • WayneEnterprises
  • KwikEMart

SERVER INSTANCE 2:

  • Shared DB
  • Umbrella

My boss stands by this design on the following believed benefits:

  • Since there's one db per company, smaller companies like KwikEMart won't suffer from the weight of the bigger ones.
  • User access can be defined on a "per-company" strategy. This way, Apu can be granted the privilege to read KwikEMart's Invoices table, but not ACME's.

Although I understand these benefits, the integrity tradeoffs seems overwhelming to me.

First, there's the obvious integrity cut-off between companies db and the shared db. It's impossible to make foreign keys across db boundaries.

Second, what if the Joker messes up with WayneEnterprises database so bad that Batman will have to restore a day-old backup? If ACME, on that very same day, decided to remove a shared Gotham address that was still in use in the older WayneEnterprises db, then every document which used that address won't be able to display it anymore. Unless of course there's a shared db backup from the exact same time that can be restored. But EVEN if there was one, it could lead to even more problems for both ACME and KwikEMart.

And that's just the two issues that popped right into my mind, there's probably others as well.

So my question here would be: are we getting in the right direction with this? And also, how does this kind of system is normally built?

Any guidance will be much appreciated.

Best Answer

In the multi tennent systems I have worked on as a DBA and Developer we used 1 database per client. That database was completely self contained and did not rely on any shared database, not even for things like the states in the US.

To make standing up a new client easy a model database was created that had all the things like States prepopulated.

The reason we did not store addresses or other common data in a shared database is that it allowed us to move the databases around several different servers to normalize the load accross the servers we had. If a database needed a higher SLA due to a client upgrade we could just take a backup and restore the client database on the appropriate server and not need to worry if "the address for Stark Industries" existed on the new server.

The obvious question is what happens when client A updates the phone number or address for a customer? Should client B see that change? Wouldn't that lead to "duplicated" data if every thing is stored in seperate databases?

What if "Stark Industries" wants your Client A using a different phone number than your Client B? Then you will have to have a way to show that and store the different numbers in the Client database or move Client A and Client B to different instances. I am sure as you look through your shared database you will find additional instances of this problem of different clients wanting to use data differently.

For updates to the common tables a script that loops through each database is rather easy to write, a cursor on sys.databases and some dynamic SQL takes care of that part.

Overall while having a shared database may look good from a normalization standpoint once you start to look at different ways that clients use the different data, a shared database may not make sense any more. If you are going to go the route of seperate databases per client, just go full bore and go completely seperate with no shared data.

Related Topic