Say we have multiple apps such as a todo app, a budget app, a calendar app, etc.
For the moment each of these apps have the following tables in common (besides their domain-related tables):
- a users table
- an organizations table
- a members table, a many-to-many joint table between users and organizations (a user may be member of multiple organizations)
Right now, obviously, the user would need to create one account per app with the current design, and repeat the profile data and organizations data.
What would be a good way for all these apps to share the users and their organizations?
Note that right now:
- the apps are just in separate repos, but it is open to be refactored/re-designed
- I do not want to have one huge Phoenix app, the apps are meant to be deployed separately, while there may be some very limited integration between those
Either have a shared DB only for the common bits (and have each app have 2x
Ecto.Repo – one with the shared stuff and one with the app-specific stuff), or introduce your own authentication microservice. I’d personally go for the first approach.
It seems that with both these options, I won’t be able to have joins and foreign keys with constraints between the users/organizations/members table and the domain-specific tables of each app.
I was thinking about “something” that could sync the tables between apps; it seems the apps can then stay simple in that way, where all the responsibility is put on that syncing mechanism and the apps can ignore the fact that the accounts and other common data are shared, and don’t need to call an external system or database.
What do you think?
If you want joins then we’re looking at a single big DB with multi-tenancy bolted on top e.g. partition by
organization_id and such.
As for periodically re-syncing credentials to app-specific DBs, I would be very wary of this idea but it can work f.ex. if you have hours during which downtime is expected or tolerated. Otherwise don’t, you are just introducing more moving parts and it’ll bite you.
It’s true that I could have just one DB as there is no overlap of tables apart from the organizations/members/users tables.
As the apps share the DB, in the migration files I will have to rely on functions such as
create_if_not_exists and handle the future updates on profile data db fields with such functions. Is this what you had in mind?
Yes. You can also easily hook up migrations to your release script – but only for one of the apps. I’ve done it.
Nitpick: if these apps are sharing a database, they are TIGHTLY COUPLED together. If you add a non-nullable field to
users then every app that signs up users will need to be updated at the same time. Pretending they are separate doesn’t change that reality (as you’ve noted with regarding migrations needing to use
If you truly want to treat the apps as separate, there needs to be a boundary. For instance, you could have a fully separate app that only handles users & organizations that other applications then use via some kind of SSO like OpenID / SAML.
Even that’s not quite the kind of sharing you’re thinking about, since having a reference to “user ID 1234” in an app won’t prevent the deletion of that user like a foreign key would…