Self-hosting
How-to

Manage database migrations

Create, review, test, apply, verify, and recover Agent Barn database migrations using Alembic in local, staging, and production environments.

For
Platform engineers, self-hosted operators, and Agent Barn contributors
On this page
  1. Overview
  2. What Agent Barn migrates
  3. Before you begin
  4. 1. Inspect migration state
  5. 2. Create a migration
  6. 3. Review the migration
  7. 4. Resolve multiple heads
  8. 5. Test the migration
  9. 6. Apply migrations locally
  10. 7. Deploy to staging
  11. 8. Deploy to production
  12. 9. Verify the migration
  13. 10. Rollback and recovery
  14. Command reference
  15. Troubleshooting
  16. Next steps

Migration outcome

A reviewed, tested, and recoverable schema change

Complete this workflow before applying an Agent Barn application database migration to a shared environment.

  • The repository has one continuous Alembic revision graph.
  • The migration has been reviewed against realistic PostgreSQL data.
  • The application image, schema, contents, and backup form one release contract.
  • Staging verification and a tested production recovery path are complete.

Overview

Agent Barn uses Alembic with SQLModel metadata to version the schema of its application PostgreSQL database.

Model changeMigrationReviewTestStagingBackupProductionVerify

Migration files live in api/migrations/versions/. The migration environment in api/migrations/env.py imports the domain models before exposing their shared SQLModel.metadata.

Alembic normally connects through DB_CONNECTION_URL. The target database therefore matters whenever you inspect, generate, apply, or reverse a migration.

What Agent Barn migrates

The self-hosted stack contains multiple PostgreSQL databases. They do not share one migration system.

DatabaseSchema ownerMigrated by Agent Barn Alembic
Agent Barn application PostgreSQLAgent Barn APIYes
LiteLLM PostgreSQLLiteLLMNo
Firecrawl PostgreSQLFirecrawlNo

The commands in this guide affect only the database referenced by the API’s DB_CONNECTION_URL.

Before you begin

You need a checkout of the agent-barn repository, a reachable PostgreSQL database, authorization to change it, and a repository-root .env with the correct DB_CONNECTION_URL. Prepare a tested backup and a maintenance or recovery plan before an incompatible production change.

Install the API dependencies from the repository root:

Install API dependencies
cd api
uv sync
cd ..

For local host commands, ensure DB_CONNECTION_URL is reachable from the host. Commands run through ./run.sh use the Docker Compose database configuration instead.

Choose a migration strategy

ChangeExamplesRecommended approach
AdditiveNullable column, new table, compatible indexOne release may be sufficient after testing
Data-transformingBackfill, normalization, identifier conversionTest representative data and verify row-level results
DestructiveDrop or rename a column, remove an enum valueUse an expand/contract sequence across releases
Long-runningLarge backfill, table rewrite, blocking indexMeasure in staging and plan a controlled maintenance window

Production migrations run before the new API rollout. During a pre-upgrade migration, the previous API may still serve requests, so the migrated schema must remain compatible with it until replacement.

Use expand and contract for breaking changes

  1. Expand: add the new schema while preserving the old schema.
  2. Migrate: backfill data and make the application support both representations.
  3. Switch: move reads and writes to the new representation.
  4. Contract: remove the old schema in a later release.

Inspect migration state

Run direct Alembic commands from api/ so the repository configuration and migration directory resolve correctly.

Applied revision
cd api
uv run python -m alembic current
Repository heads
cd api
uv run python -m alembic heads
Migration history
cd api
uv run python -m alembic history --verbose

The repository expects exactly one head. Run the canonical check from its root:

Shell
make check-migrations

If the database is behind the repository head, determine why before generating another revision. Autogeneration against an outdated or incorrect database can produce misleading operations.

Create a migration

Update the relevant SQLModel models first. When adding a model module, ensure the migration environment imports it before SQLModel.metadata is evaluated.

Shell
make makemigrations

Enter a short message when prompted, such as add agent retention policy. Alembic creates an autogenerated revision under api/migrations/versions/ with a filename resembling <revision>_add_agent_retention_policy.py.

The revision defines revision, down_revision, branch_labels, depends_on, upgrade(), and downgrade().

Review the migration

Read the entire generated revision before applying it. Confirm down_revision targets the intended current head, the graph remains continuous, and make check-migrations reports one head.

Review generated operations

  • Unexpected table or column deletion, or a rename represented as drop and add
  • Nullability changes without a backfill and unique constraints existing data may violate
  • Foreign keys, indexes, and table rewrites that may conflict with rows or hold locks
  • Server defaults, PostgreSQL enums, and type changes that require an explicit USING expression
  • Missing application fields or operations caused by connecting to the wrong database

Review data transformations

Make transformations deterministic and safe for the expected volume. Account for malformed values, intermediate uniqueness, stable ordering, foreign keys, lock duration, and transaction failure. A uniqueness migration may require a collision-free temporary state.

Review the downgrade

Reverse the revision intentionally when reversal is safe. If a downgrade destroys data or cannot reconstruct the old representation, document that limit, test the real recovery strategy, require a backup, and prefer a forward corrective migration after production data changes.

Resolve multiple heads

Multiple heads usually appear when branches independently add revisions from the same parent. Inspect both branches before merging:

Shell
make check-migrations

cd api
uv run python -m alembic heads
uv run python -m alembic history --verbose

Confirm that both branches are compatible, especially when they touch the same table, constraint, column, enum, or data set. Then create the merge revision from the repository root:

Shell
make merge-heads

The command fails when no heads exist, does nothing with exactly one head, and creates a merge revision only for multiple heads. A merge revision normally has multiple down_revision values and empty upgrade and downgrade functions.

Test the migration

Test against PostgreSQL, not an approximation. The API suite starts a temporary PostgreSQL database and upgrades it to Alembic head before tests:

API CI checks
make check-api
make check-migrations
make test-api

API CI runs make check-migrations. The test path proves the complete migration chain can build a clean database.

Test existing data

Use a staging-sized or sanitized realistic copy for backfills, constraints, enum or type changes, identifier rewrites, destructive operations, and work that may hold long locks. Verify both schema and affected rows.

Test downgrade and reapplication

Shell
make rollback
make migrate

Confirm the prior revision, old-application compatibility, data preservation, successful reapplication, and the final upgraded result. make rollback runs alembic downgrade -1; do not use it casually on a shared database.

Use an isolated database override

Shell
cd api
ALEMBIC_DB_URL='postgresql+psycopg2://USER:PASSWORD@HOST:PORT/DATABASE' \
  uv run python -m alembic upgrade head

ALEMBIC_DB_URL overrides the normal connection for isolated migration tests. Use secret injection rather than placing production credentials in shell history.

Apply migrations locally

Full local stack

Shell
./run.sh

The script starts PostgreSQL and Redis, builds the API image, runs alembic upgrade head in a temporary API container, then starts the API, worker, and UI. Application services do not start when migration fails.

Host-managed development

Shell
make migrate

cd api
uv run python -m alembic current

Do not mix host-managed services and the full Docker application stack against the same development workflow unless you deliberately understand the process and database used by each command.

Deploy to staging

Pass every schema-changing release through agent-farm-staging. Confirm it has independent application data and credentials, a current backup, one Alembic head, recorded start and target revisions, and an explicit recovery choice.

The API chart creates an agentbarn-api-migrate pre-install/pre-upgrade Job. It uses the target API image and runs:

Shell
cd /app/api && alembic upgrade head

The Job must complete before Helm rolls out the new API. After deployment, verify API health, administrator login, the changed behavior, workers, Event Deliveries, Activity, Tool Calls, logs, costs, restart recovery, migration duration, and observed locking.

Deploy to production

Confirm the exact commit and API image, one Alembic head, representative staging results, backward compatibility with the old API, a verified application database backup, the matching AGENT_TOKEN_ENCRYPTION_KEY, and named verification and recovery owners. Prevent overlapping deployments and communicate any maintenance window.

The migration Job has backoffLimit: 2. Successful hook Jobs are deleted; failed Jobs remain for diagnosis.

Inspect a failed migration Job
kubectl get job agentbarn-api-migrate \
  --namespace agent-farm

kubectl describe job agentbarn-api-migrate \
  --namespace agent-farm

kubectl logs job/agentbarn-api-migrate \
  --namespace agent-farm
Locate a retained migration pod
kubectl get pods \
  --namespace agent-farm \
  --selector app.kubernetes.io/component=migration-job

Do not repeatedly redeploy until you know whether the failed attempt committed schema or data changes.

Verify the migration

Check the database revision from the deployed production API environment:

Deployed Alembic revision
kubectl exec \
  --namespace agent-farm \
  deployment/agentbarn-api \
  -- sh -c 'cd /app/api && alembic current'

Confirm it matches the release head, then check the public API using the actual production hostname:

API health
curl --fail https://api.agentbarn.example.com/api/v1/health

Verify API and UI health, changed behavior against old and new records, Organization isolation, authorization, workers, reconciliation, affected Agent lifecycle operations, telemetry and cost ingestion, database connections, error rates, schema-related logs, migration duration, and unexpected locks.

Record the starting and target revisions, deployment commit and image, start and finish time, backup identifier, verification results, and corrective actions.

Rollback and recovery

SituationPreferred response
Migration did not startFix deployment configuration and retry
Migration failed and transaction rolled back cleanlyDiagnose the error, correct the migration, and redeploy
Migration succeeded but new API failedKeep or restore an application version compatible with the migrated schema
Migration introduced a correctable schema problemCreate and deploy a forward corrective migration
Tested downgrade is safe and data-preservingRun the controlled downgrade procedure
Migration destroyed or irreversibly transformed dataStop writes and restore the verified recovery set
Database state is uncertainPause deployment and inspect revision, schema, data, and migration logs

Application rollback

A Helm rollback changes Kubernetes manifests and images. It does not run alembic downgrade. Confirm the older image can use the migrated schema before restoring it.

Alembic downgrade

Shell
make rollback

This downgrades one revision using the locally configured database. A production downgrade needs a reviewed procedure, a precise target, representative testing, understood data-loss behavior, controlled writes, application compatibility, and a current backup.

Database restoration

  1. Stop or isolate writers.
  2. Preserve logs and the failed database for investigation.
  3. Restore the application database backup.
  4. Restore the matching stable encryption key when rebuilding the environment.
  5. Deploy an image compatible with the restored revision.
  6. Verify the Alembic revision and run application and data-integrity checks.
  7. Reopen traffic only after verification succeeds.

Command reference

Run Make targets from the repository root.

CommandPurpose
make makemigrationsPrompt for a message and generate an autogenerated revision
make migrateUpgrade the configured database to head
make rollbackDowngrade the configured database by one revision
make merge-headsCreate a merge revision when multiple heads exist
make check-migrationsFail unless the repository has exactly one Alembic head
make test-apiRun API tests against PostgreSQL migrated to head
./run.shStart the local stack and migrate before starting application services

Run direct inspection commands from api/.

CommandPurpose
uv run python -m alembic currentShow the revision applied to the configured database
uv run python -m alembic headsShow the repository’s current migration heads
uv run python -m alembic history --verboseShow the revision graph and migration history
uv run python -m alembic upgrade headApply all pending migrations
uv run python -m alembic downgrade -1Reverse one revision

Operational safety checklist

Before production

  • One Alembic head and a manually reviewed revision
  • Upgrade testing against representative PostgreSQL data
  • Tested downgrade or forward-recovery behavior
  • Old-API compatibility and verified staging deployment
  • A recoverable backup with matching stable keys
  • Recorded revisions, deployment controls, and available owners

After production

  • The database reports the expected revision
  • API and UI health checks pass
  • Changed data and behavior are verified
  • Workers and reconciliation are healthy
  • Logs contain no unexplained schema errors
  • The release record contains backup and verification results

Troubleshooting

SymptomLikely causeResolution
make check-migrations reports multiple headsParallel branches created migrations from the same parentReview both branches for conflicts, then run make merge-heads
Autogeneration wants to drop unrelated tablesAlembic loaded incomplete model metadata or connected to the wrong databaseVerify model imports and DB_CONNECTION_URL before keeping the revision
Autogeneration creates no operationsThe model was not imported or the database already matches itCheck api/migrations/env.py, model registration, and the target database
Migration cannot connect locallyDB_CONNECTION_URL is missing or not reachable from the hostCorrect the repository-root .env or run through the Docker workflow
Migration fails on existing rowsA new constraint or type conflicts with production-shaped dataAdd a validated backfill or split the change into expand and contract revisions
A unique backfill collidesIntermediate values violate an existing unique constraintUse a deterministic collision-free intermediate state
Kubernetes upgrade stops at the migration hookThe Alembic Job failed before application rolloutInspect the retained Job and pod logs before retrying
No successful migration Job exists to inspectSuccessful hook Jobs are deletedVerify alembic current from the running API pod
Helm rollback leaves the application brokenThe database remained at the newer revisionDeploy a compatible image, run a tested downgrade, or restore the database
Old API fails during the pre-upgrade hookThe migration was not backward-compatibleRestore service, then redesign the change using expand and contract
Migration is much slower in productionStaging data volume or lock behavior was not representativeStop repeated attempts, assess locks, and schedule a controlled migration
make rollback affects the wrong environmentThe configured connection targeted another databaseStop, preserve evidence, assess changes, and recover from the appropriate backup
LiteLLM or Firecrawl schema is unchangedAgent Barn Alembic does not manage those databasesFollow the migration process supplied by the owning upstream service

Next steps

Continue operating the platform Monitor the platform → Configure signals for database, API, worker, Agent, and provider failures.
Documentation