Self-hosting
How-to

Manage database migrations

Create, review, apply, verify, and recover Agent Barn migrations for Product, Ingest, Communications, Connection data, and PostgreSQL-backed delivery.

For
Platform engineers, self-hosted operators, and Agent Barn contributors
On this page
  1. Overview
  2. What Agent Barn migrates
  3. Communications data and legacy transition
  4. Before you begin
  5. 1. Inspect migration state
  6. 2. Create a migration
  7. 3. Review the migration
  8. 4. Resolve multiple heads
  9. 5. Test the migration
  10. 6. Apply migrations locally
  11. 7. Deploy to staging
  12. 8. Deploy to production
  13. Protect encrypted Communications data
  14. 9. Verify the migration
  15. 10. Rollback and recovery
  16. Command reference
  17. Troubleshooting
  18. 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.

Agent Barn Alembic covers Organizations and Memberships, Agents and Agent Access, Templates and Skills, Agent Secrets and Shared Credentials, Communication Connections, Communication Deliveries, canonical Conversation Messages, the Communications operational journal, Tool Calls, Domain Events and Event Deliveries, costs, and related operational records. Communications uses this shared application schema; it has no separate migration system.

Communications data and legacy transition

Current Communications persistence includes records equivalent to communication_connection, communication_delivery, communication_journal_entry, and agent_chat_message with required connection_id. Each Connection belongs to one Agent and Organization; each Delivery belongs to one Connection. Canonical Conversation Messages carry their source Connection, and location identity includes Connection ID and channel ID.

Provider message identity is unique within a Connection. Retired Connections are preserved so Conversation history remains attributable, while Connection credentials remain encrypted. This is operational guidance, not a complete schema reference.

Legacy single-Platform Agents

For installations upgrading from the removed single-Platform Agent architecture, the transition creates generic Communication Connections, converts supported legacy Platform configuration into Connection settings and encrypted credentials, backfills the generated Connection ID onto compatible Conversation Messages, and creates Connection-scoped indexes and constraints. Later revisions remove legacy Agent Platform fields, Platform-specific configuration tables, and the obsolete per-user Slack configuration-token table. New Agents are headless and do not have a platform field.

Legacy deployments may contain duplicate provider credentials on different Agents. Where required, migration preserves otherwise valid legacy records using a legacy-scoped compatibility identity; newly created Connections remain subject to current provider-identity uniqueness rules. Do not manually duplicate new provider credentials after migration.

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:5432/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, applies alembic upgrade head, and only then starts Product API, Ingest, the Domain Event worker, Communications, and UI, alongside local Kubernetes dependencies. Application services do not start when migration fails.

Host-managed development

Start the three HTTP processes
make dev-api

make dev-api starts Product API on 8000, Ingest on 8001, and Communications on 8002.

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.

Use this process order: back up the application database; preserve encryption and signing keys; make the new image available; apply Alembic migrations; confirm the intended head; roll Product, Ingest, Communications, and worker processes to compatible code; confirm Communications starts; check Connection and Delivery data through authorized surfaces; then run a Connection-level message canary. A new Communications process must not run against an older incompatible schema.

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

Communications uses the same application schema and API image tag as Product API; it does not run an independent migration job. The hook must complete before the new Communications workload is considered ready, and migration failure should stop the rollout rather than be ignored. After deployment, verify authorized Connection and Delivery reads, Communications startup, provider health, Tool Calls through Ingest, workers, Event Deliveries, Activity, logs, costs, migration duration, and observed locking.

A database migration does not start or stop Agents, rebuild Runtime pods, reconnect provider sessions, reinstall provider applications, rewrite Platform policies, or rotate provider credentials. Once the new Communications process starts, it reconciles enabled Connection sessions from the migrated database state.

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.

Protect encrypted Communications data

Legacy provider-configuration backfill requires AGENT_TOKEN_ENCRYPTION_KEY when encrypted provider configuration exists. The migration uses the existing key to decrypt legacy provider credentials, re-encrypt them into Connection credential envelopes, and generate encrypted Connection driver credentials.

The same key must be available to the migration process, Product API, Communications, and every replica reading the resulting data. If it is missing or incorrect, migration should fail rather than silently create unusable Connections.

COMMUNICATION_JOURNAL_RETENTION_DAYS=31 is the default content-free journal retention. Valid values range from 1 through 3650. The Communications supervisor prunes journal entries; pruning is not an Alembic migration, changing retention needs no schema migration, and pruning does not delete canonical Conversation Messages. Do not confuse absent old journal rows with a failed schema migration.

  • Preserve the application-database backup, AGENT_TOKEN_ENCRYPTION_KEY, and signing key.
  • Record current deployed image identifiers, Alembic revision, and environment-specific Secret configuration.
  • Keep real Secret values out of command output and migration logs.

Restoring only the database without the matching encryption key is not usable credential recovery.

Replica safety

Only one migration runner applies schema changes. Communications replicas must not execute Alembic on startup; PostgreSQL ingress leases coordinate provider sessions, not migration ownership. Old and new processes overlap only when migration compatibility is intentional, and the Helm migration hook remains the canonical production runner.

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 one Alembic head, Communication Connection tables, Agent and Organization ownership on active Connections, encrypted non-readable credentials, non-null Connection IDs on canonical Conversation Messages, expected Connection references on Delivery and journal rows, Product API Connection listing, Communications access to enabled Connections, provider health after rollout, Connection-aware Conversation reads, and Tool Call telemetry through Ingest separately. Prefer authorized Product API and UI checks over printing encrypted or decrypted credential columns.

Connection canary

  1. Open an existing migrated Agent and confirm its expected Communication Connection, settings, and external identity where available.
  2. Confirm the credential value is not returned; enable the Connection if appropriate and start the Agent if stopped.
  3. Send one provider message that passes policy and confirm it appears under the expected Connection.
  4. Confirm inbound and outbound Delivery lifecycle completion, then confirm Tool Calls still appear through Ingest.

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; it is not a complete deployment rollback. Before downgrading, review whether the revision drops Communications data, recreates legacy tables, loses fields without a legacy representation, deletes Conversation rows, conflicts with running code, needs the historical encryption key, or can preserve newly created Connections. Application rollback and database downgrade are separate decisions. Do not downgrade across the headless-Agent or Connection transition without a tested recovery plan.

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 with Self-hosting Communications, self-hosting configuration, Deploy Kubernetes, and Communication diagnostics for the operational checks around a migrated release.

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