Build fast, launch faster, scale when necessary.
This guide provides the essential commands to manage Ecto migrations in a Fly.io production environment via SSH console for the CodeHorizon application.
First, connect to your Fly.io app console:
fly ssh console -a code-horizon-app
To see which migrations are applied (UP) or pending (DOWN):
/app/bin/code_horizon eval "
{:ok, _, result} = Ecto.Migrator.with_repo(CodeHorizon.Repo, fn repo ->
migrations_path = Application.app_dir(:code_horizon, \"priv/repo/migrations\")
migrations = Ecto.Migrator.migrations(repo, migrations_path)
IO.puts(\"Migration Status:\")
IO.puts(\"=================\")
Enum.each(migrations, fn {status, version, description} ->
status_str = case status do
:up -> \"✓ UP \"
:down -> \"✗ DOWN\"
end
IO.puts(\"#{status_str} #{version} #{description}\")
end)
end)
"
To apply all pending migrations:
/app/bin/code_horizon eval "
{:ok, _, _} = Ecto.Migrator.with_repo(CodeHorizon.Repo, fn repo ->
Ecto.Migrator.run(repo, :up, all: true)
end)
"
To rollback to a specific migration version (e.g., before create_agents migration):
/app/bin/code_horizon eval "
{:ok, _, _} = Ecto.Migrator.with_repo(CodeHorizon.Repo, fn repo ->
Ecto.Migrator.run(repo, :down, to: 20250707211106)
end)
"
To migrate up to a specific version:
/app/bin/code_horizon eval "
{:ok, _, _} = Ecto.Migrator.with_repo(CodeHorizon.Repo, fn repo ->
Ecto.Migrator.run(repo, :up, to: 20250710215612)
end)
"
If you have a "FILE NOT FOUND" migration entry in your schema_migrations table:
/app/bin/code_horizon eval "
{:ok, _, _} = Ecto.Migrator.with_repo(CodeHorizon.Repo, fn repo ->
import Ecto.Query
from(s in \"schema_migrations\", where: s.version == ^20250710215612)
|> repo.delete_all()
IO.puts(\"Removed migration 20250710215612 from schema_migrations table\")
end)
"
You can also run these commands directly from your local machine without entering the SSH session:
fly ssh console -a code-horizon-app --command "/app/bin/code_horizon eval '{:ok, _, _} = Ecto.Migrator.with_repo(CodeHorizon.Repo, fn repo -> Ecto.Migrator.migrations(repo, Application.app_dir(:code_horizon, \"priv/repo/migrations\")) end)'"
fly ssh console -a code-horizon-app --command "/app/bin/code_horizon eval '{:ok, _, _} = Ecto.Migrator.with_repo(CodeHorizon.Repo, fn repo -> Ecto.Migrator.run(repo, :down, step: 1) end)'"
fly ssh console -a code-horizon-app --command "/app/bin/code_horizon eval '{:ok, _, _} = Ecto.Migrator.with_repo(CodeHorizon.Repo, fn repo -> Ecto.Migrator.run(repo, :up, all: true) end)'"
You need to run the following command
fly mpg proxy
? Select Organization: Code Horizon (code-horizon)
? Select a Postgres cluster code-horizon-managed-db (iad)
Proxying localhost:16380 to remote ...
fly ssh console
cd bin
./code_horizon remote