Open Martinsos opened 3 years ago
Two commands they added in Prisma 3.13.0 (https://github.com/prisma/prisma/releases/tag/3.13.0) are also interesting:
migrate diff
db execute
They are worth checking out while we are figuring out how to best deal with migrations!
I have a coworker that has drilled into me the value of forward-only migrations (no renaming, no dropped columns). By doing this, you can migrate before deployment, and you dont worry about the application going down. Once you deploy, your two apps can exist simultaneously without any problems. Over time, when you are confident the column is "dead", you can drop it, also without any problems.
This is a developer practice that is rarely seen, but it is kind of the only way to really do this safely.
Oh that sounds great! Aha so basically you ensure that you have a database that supports both old/currentl release and new release, so you can publish new release without modifying the database at the same time, instead you first prepare the DB, all works, then you do the new release. Yup, that is perfect, I remember at last job we were also trying to do it that way! I am not sure if we can somehow enforce that in Wasp though hm, maybe it could be an advice instead.
As stated in Prisma docs:
Right now we run
migrate deploy
inside the deployed docker container whenever the app is started, as a part of command that launches the app, which is good in the sense that it is not run locally, but it is bad because it runs too often (every time app starts instead of once when it is deployed) and also ifmigrate deploy
fails we are left with the crashed app that doesn't run.So Prisma recommends to make it a part of CI. Unless we are generating the CI files ourselves, the only way we can do this is by offering users a command that they can put into their CI. They can then also run this command locally if they want.
So, what we really need to do is let users run
migrate deploy
on their own, probably by having a command likewasp db migrate-prod
or smth like that. They can then use it locally or in CI if they have it, as a step before pushing the docker container. They will however need to provide DATABASE_URL for a prod database. We don't want this in .env file since it is stored on their machine, that is dangerous. But, we can ask them to input it, or for example they can get it from Heroku withheroku config:get DATABASE_URL -a <app_name>
, or they can provide it via env var directly in their command line. Once we do this, we should remove themigrate deploy
from docker container and describe in docs they have to run it on their own.One thing that I am worried about here is: what happens in the time between successful
migrate deploy
and successful deployment of actual server? What if deployment of server doesn't work or takes long time? We have app in the wrong state for some time. Can we roll-back easily? I am guessing there is no easy solution for this and we need a mechanism on the hosting provider side to handle this. Actually, looking at Heroku, they talk about this here https://devcenter.heroku.com/articles/release-phase -> it is specifically meant for these purposes (db migrations). From reading this, it seems we should domigrate deploy
betweenheroku container:push
andheroku container:release
-> we can just tell users to do it this way. They also have special mechanism on Heroku to do this completely with containers: you push a container that you want to use inrelease' phase, and then you call upon it when you are calling
container:releasefor whatever you are releasing. So in our case, we would prepare container (by adding target to dockerfile) that runs
prisma migrate deploy` and then users would have extra step between server container push and release, so all together it would be:So, two obvious approaches seem to be a command to do it and container that does it, let's see what makes more sense.