Share migrations in monorepo
I am using drizzle in a monorepo (npm workspaces with turborepo) within an internal package that is shared among multiple apps. It basically exports a bunch of functions that use drizzle behind the scenes.
This works great, however I can't run migrations from within the apps that use the package, because the folder with the migrations is only available inside the package that contains drizzle. I would love to run the migrations on app startup using
migrate
from drizzle-orm/postgres-js/migrator
like shown in the examples, but then I get the error that the migrations can't be found.
The only solution I figured so far is to copy the migrations from the shared package to every app directory every time when I ran drizzle-kit generate
. Can you think of any better solutions?8 Replies
Hey, just say your message on stackoverflow and then remembered there was a help topic here, but just didn't have a chance to answer
and now I found you
Let's chat here I guess
You can run
drizzle-kit generate
regardless of the structure you'll have. It can be a separate module that has drizzle-kit dependencies and uses a schema file plus an output folder to store migrations.
The best approach would be to bundle the migrations folder in an app that executes migrations on app startup. I don't think you need to copy them to every package you have. However, if you don't have a "main" package, then I suppose each subpackage in the monorepo should bundle the migrations folder and run migrations on each app startup.
I can provide more assistance if I can see some basic setup, perhaps a minimal reproducible example repository, so I can suggest some changes in a PR or something.Hey Andres, thanks for your time and the response - I really appreciate this. I made a really simple example repo to illustrate my question: https://github.com/BenBestmann/drizzle-monorepo
The README contains more explanations. The main idea is that I want to encapsulate all database and business logic in an internal packages like the
core
package of the example repo and then use this package in multiple apps of the repo (e.g. web, mobile, backend), see the example Next.js app included (esp. page.tsx
file).
The approach works fine, except for the migrations. I would love to execute them in every app on startup like you illustrate in the docs because I find it very convenient, esp. in development. However as the core
package is just an internal npm workspace with no build, when I execute the Client.migrate()
function from within the apps they are looking for the migrations directory and of course can't find them.
It somehow feels wrong to copy the migrations into every app, as I want the core package to be the single source of truth where I define all schema. Another alternative I can think of is to create a simple npm script in the core
package that runs the migrations which I then manually inovke in development and via a CI solution during deployments.
Do you have any other ideas? I also can think of using your push
command, but we are using Postgres.
Thanks again for taking the time! Best regards, Ben.GitHub
GitHub - BenBestmann/drizzle-monorepo
Contribute to BenBestmann/drizzle-monorepo development by creating an account on GitHub.
Sorry, I of course ment to type Andrew not Andres 😉
If my last name was San it actually may fit well
San Andres
It's a bit late here but I can take a look tomorrow and will try to help you
Of course, thanks! Looking forward to your ideas.
Ok, so what you need to do is to have only 1 package responsible for migrations.
As long as this package is
core
and not backend
, you'll need to go with the CI approach and run migrations in CI right before server start.
Another solution would be to make the backend
responsible for migrations, and only the backend
, because neither the web
nor mobile
should be responsible for it.
So let's say you can have a core
package containing all schemas and database calls, but generate migrations directly to the backend
folder.
In this case, you'll still have a source of truth for all types in the core
package, but SQL files generated from the kit will "live" in the backend
and be executed when the backend
starts. This means that if any new migration was created, you will need to redeploy the backend
module.Thanks man, this helps. I like the idea with exporting the migration files to the backend. Nevertheless I think I will keep everything inside the core package, as it just feels more consistent. I will run the migrations via CI on deploy and during dev I will just use sth. like nodemon to automatically run migrations.
drizzle-kit
does not have a command yet to execute migrations, right? So I guess I will just write a little script to execute migrate()
then? Also really looking forward for the release of drizzle-kit push
for PostgresSQL.
Thanks again for taking the time and your support! Drizzle is an awesome idea and I hope and guess you will habe great success with it! Defintely like it so far ✌️If anyone comes here looking for an example solution, this is what I got:
migrate.ts
in my database package
Got this script command in my package.json
Then here's an example .yml
for a GitHub Action
Thanks for the great discussion everyone!