michaelfich

michaelfich

How to move an existing database into a multi-tenant configuration?

Hey all,

I’ve been working on a project where I need to move an existing database into a multi-tenant configuration.

We have some migrations that we want to run outside of individual tenants (creating enums, etc) to be run from priv/repo/migration, and also a set of migrations we want to run to generate tables for each individual tenant from priv/repo/tenant_migrations.

Ideally I would want the migrations to run for all of these sequentially whenever I run mix ecto.migrate on the single database, in the following order:

  1. public
  2. tenant_1
  3. tenant_2
  4. tenant_3
  5. etc…

Additionally I do not wish maintain multiple pools of database connections to the same database, if possible, though it would be nice to be able to have separate Ecto Repo’s for each tenant, to make queries such as:

MyApp.Repo.Tenant1.all(query)

# -- or --

MyApp.Repo.all(query, prefix: "tenant_1")

I’ve been able to run these migrations properly from the command line through multiple commands, by doing the following:

mix ecto.migrate

mix ecto.migrate --prefix=tenant_1 --migrations-path=priv/repo/tenant_migrations/

mix ecto.migrate --prefix=tenant_2 --migrations-path=priv/repo/tenant_migrations/

mix ecto.migrate --prefix=tenant_3 --migrations-path=priv/repo/tenant_migrations/

If possible, it would be nice to configure each Repo with a shared connection pool and then have their own set of migrations. One of the issues I encountered while trying to define a separate Repo for each tenant was that running mix ecto.create or mix ecto.drop, it tries to do create or drop the database multiple times; working the first and failing the rest of the times.

I’ve scoured the Ecto and EctoSQL libraries for documentation on this and tried multiple solutions I’ve come across, but it’s not yet produced a solution that works yet aside from running multiple ecto.migrate mix tasks as demonstrated above.

Has anyone come across this use-case and able to point me in the right direction? Any assistance would be greatly appreciated.

Most Liked

l00ker

l00ker

Have you looked at Triplex?

https://github.com/ateliware/triplex

al2o3cr

al2o3cr

Like @l00ker said, take a look at triplex; the process you described that you want is so similar to how that package works I thought you might be using it already.

al2o3cr

al2o3cr

I can understand this concern for some libraries, but take the time to read through the Triplex code: there’s not much of it, and what’s there is mostly gluing together things that already exist. All the actual “tenent enforcement” is delegated to Ecto’s prefix machinery.

Where Next?

Popular in Questions Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 127089 1222
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52673 488
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
klo
Got a question about when to concat vs. prepending items to list then reversing to achieve appending. So i know lists boil down to [1 | ...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement