Fly Database Migrations
Running database migrations on deploy
When to use this page
- You need schema migrations to run automatically during Fly deployments.
- You want deployment to stop safely when migrations fail.
Prerequisites
- Application already deployable on Fly.
- Migration command/script available in your project.
- Dockerfile supports custom entrypoint.
When deploying to Fly.io, migrations should run before new instances serve traffic. Fly handles this with release commands executed after build and before rollout.
Step 1: Create entrypoint script
We recommend using a single entrypoint.sh that accepts a command argument. This way the same script serves as both the server start command and the migration runner:
#!/bin/sh
set -e
COMMAND="${1:-server}"
if [ "$COMMAND" = "server" ]; then
echo "Starting server..."
node --max-old-space-size=1024 ./main.js
elif [ "$COMMAND" = "migrate" ]; then
echo "Running migrations..."
node ./drizzle-migrate.js
else
echo "Usage: entrypoint.sh [server|migrate]"
exit 1
fiDrizzle migration script
For a ready-to-use Drizzle migration script, check out drizzle-migrate.ts from our boilerplate.
Make sure the script is executable:
chmod +x entrypoint.shStep 2: Add script to Dockerfile
Ensure the entrypoint script is copied into your Docker image and set it as the ENTRYPOINT:
COPY entrypoint.sh /app/entrypoint.sh
ENTRYPOINT [ "./entrypoint.sh" ]Since the entrypoint defaults to server, your app will start normally. The migrate argument is only passed by the release command during deploys.
Step 3: Configure fly.toml
Add the migration as a release command:
[deploy]
release_command = "migrate"Because ENTRYPOINT is set in the Dockerfile, Fly passes migrate as the argument to entrypoint.sh, which triggers the migration branch of the script.
Release command failures
If the release command fails (non-zero exit code), the deployment is halted and the previous version of your app continues running. Check the output with fly logs to debug migration issues.
How it works
- You run
fly deploy - Fly builds your Docker image
- Fly creates a temporary Machine and runs the release command (your migration script)
- If the migration succeeds, Fly rolls out the new Machines
- If the migration fails, the deploy is aborted
Verify
- Deploy output shows release command executed successfully.
- New app version starts only after migration success.
- Database schema version matches expected migration state.
Troubleshooting
release_commandnot running: Confirm[deploy] release_command = "migrate"exists infly.toml.- Script permission denied:
Ensure
chmod +x entrypoint.shis executed before image build. - Deploy blocked by migration error:
Inspect release logs with
fly logsand fix migration script idempotency issues.