michaelfich
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:
publictenant_1tenant_2tenant_3- 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.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










Showing Posts 1 to 9- Show Best Posts
- Show All Posts (oldest first)
- Show All Posts (newest first)
l00ker
Have you looked at Triplex?
https://github.com/ateliware/triplex
l00ker
I know this is a bit of a stretch, but… I just started playing with Ash Framework and I noticed that it has multi-tenancy built in.
I say a bit of a stretch because it might be too much all at once. I decided to try Ash with a section of an app I’m working on and so far so good, but it is quite a lot to ingest.
Just another option to consider.
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.michaelfich
Hey guys, thanks for the responses!
I’ve taken a look at Triplex and it looks promising but one of the internal concerns we have is that it hasn’t had a new release in nearly 4 years so I’m not sure if we want to use such a dependency on something that’s important to our project.
I’m hoping to be able to complete this with just Ecto/EctoSQL alone if possible to migrate an existing project with several hundred migrations into a multi-tenant DB
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
prefixmachinery.cjbottaro
I start a separate
Ecto.Repoper Postgres server. Each server holds many tenants (as Postgres schemas).Then you use these callbacks…
put_dynamic_repo/1
get_dynamic_repo/0
default_options/1
to determine which
Ecto.Repoto use and also set the prefix (schema).Then I wrote my own
mix ecto.tenants.migratewhich usesTask.async_streamto migrate all tenants, delegating out to the existing migration functions, kinda looking at howmix ecto.migratedoes it.Ecto is close to having multi-tenancy out of the box… it’s just missing like one callback (something to list all the tenants) and a migration task that basically iterates over all tenants, calling the normal migration code.
michaelfich
That makes a lot of sense when the use-cases is separate databases.
I was curious if anyone could point me in the right direction for different schemas within the same database as well.
joddm
You can specify prefixes inside the migration code:
Multi tenancy with query prefixes — Ecto v3.9.4 (hexdocs.pm)
cjbottaro
It’s even easier because you just have one repo. Then you just use the
default_options/1callback to automatically set the prefix.Then your migration code is something like…
Note the
migration_lock: false. Last I checked, the code that does migration locking does not honor the:prefixoption. Should probably open a GitHub issue about that.