Skip to content

Migration Guide

Purpose: Upgrade between Fulcrum versions safely Audience: Operators managing Fulcrum deployments Format: Step-by-step procedures for each migration path


Before Any Migration

Pre-Migration Checklist

  • [ ] Back up your database
  • [ ] Document current policy configuration
  • [ ] Review release notes for breaking changes
  • [ ] Plan maintenance window (if production)
  • [ ] Test migration in staging first

Backup Procedures

Database Backup:

# Local development
docker compose -f docker-compose.unified.yml exec fulcrum-postgres \
  pg_dump -U fulcrum fulcrum > backup-$(date +%Y%m%d).sql

# Production (Railway)
railway run pg_dump -Fc > backup-$(date +%Y%m%d).dump

Export Policies:

curl http://localhost:8080/api/v1/policies > policies-backup.json

Export Configuration:

curl http://localhost:8080/api/v1/config > config-backup.json


Version 0.x to 1.0 Migration

Breaking Changes in 1.0

Area Change Action Required
API /api/v1/check renamed to /api/v1/evaluate Update API calls
SDK client.check() renamed to client.evaluate() Update SDK usage
Policy Schema action field renamed to decision Update policy JSON
Database New columns in policies table Run migrations

Step 1: Update SDKs First

Python:

pip install --upgrade fulcrum-governance>=1.0.0

Update code:

# Before (0.x)
result = env.check("send_email", input_text=content)

# After (1.0)
result = env.evaluate("send_email", input_text=content)

TypeScript:

npm install @fulcrum-governance/sdk@^1.0.0

Update code:

// Before (0.x)
const result = await envelope.check('send_email', content);

// After (1.0)
const result = await envelope.evaluate('send_email', content);

Step 2: Update API Calls

If calling the API directly:

# Before (0.x)
curl http://localhost:8080/api/v1/check -d '...'

# After (1.0)
curl http://localhost:8080/api/v1/evaluate -d '...'

Step 3: Run Database Migrations

Local Development:

docker compose -f docker-compose.unified.yml down
docker compose -f docker-compose.unified.yml pull
docker compose -f docker-compose.unified.yml up -d
Migrations run automatically on startup.

Production (Railway):

# Pull latest version
railway up

# Verify migrations completed
railway logs | grep -i migration

Step 4: Update Policy Definitions

Export, transform, and re-import:

# Export current policies
curl http://localhost:8080/api/v1/policies > policies.json

# Transform (update field names)
jq '[.[] | .decision = .action | del(.action)]' policies.json > policies-v1.json

# Re-import
curl -X POST http://localhost:8080/api/v1/policies/import \
  -H "Content-Type: application/json" \
  -d @policies-v1.json

Step 5: Verify Migration

# Check version
curl http://localhost:8080/version
# Expected: {"version": "1.0.0", ...}

# Test policy evaluation
curl -X POST http://localhost:8080/api/v1/evaluate \
  -H "Content-Type: application/json" \
  -d '{
    "action": "test_action",
    "input_text": "test",
    "workflow_id": "migration-test"
  }'

Minor Version Upgrades (1.x to 1.y)

Minor versions are backward compatible. No code changes required.

Upgrade Procedure

Local Development:

docker compose -f docker-compose.unified.yml pull
docker compose -f docker-compose.unified.yml up -d

Production (Railway):

# Update to specific version in railway.toml
# Then deploy
railway up

SDKs:

# Python
pip install --upgrade fulcrum-governance

# TypeScript
npm update @fulcrum-governance/sdk

Post-Upgrade Verification

# Health check
curl http://localhost:8080/health

# Version check
curl http://localhost:8080/version

# Quick functional test
curl -X POST http://localhost:8080/api/v1/evaluate \
  -d '{"action": "test", "input_text": "hello", "workflow_id": "test"}'

SDK Version Compatibility

Server Version Python SDK TypeScript SDK
0.1.x 0.1.x 0.1.x
1.0.x 1.0.x - 1.1.x 1.0.x - 1.1.x
1.1.x 1.0.x - 1.2.x 1.0.x - 1.2.x

Rule: SDK minor version can be higher than server, but not lower.


Database Migration Reference

Checking Migration Status

# Local
docker compose -f docker-compose.unified.yml exec fulcrum-server \
  /app/migrate status

# Production
railway run /app/migrate status

Manual Migration (if needed)

# Apply pending migrations
docker compose -f docker-compose.unified.yml exec fulcrum-server \
  /app/migrate up

# Rollback last migration
docker compose -f docker-compose.unified.yml exec fulcrum-server \
  /app/migrate down 1

Migration Files

Located in migrations/ directory:

migrations/
├── 001_initial_schema.sql
├── 002_add_policies_table.sql
├── 003_add_traces_table.sql
├── 004_add_semantic_fields.sql
└── ...


Self-Hosted to Cloud Migration

Moving from self-hosted to Fulcrum Cloud (api.fulcrumlayer.io):

Step 1: Export Data

# Export policies
curl http://localhost:8080/api/v1/policies > policies-export.json

# Export configuration
curl http://localhost:8080/api/v1/config > config-export.json

Step 2: Create Cloud Account

  1. Sign up at fulcrumlayer.io
  2. Create tenant and obtain API key
  3. Note your Tenant ID from dashboard

Step 3: Import to Cloud

# Import policies
curl -X POST https://api.fulcrumlayer.io/api/v1/policies/import \
  -H "X-API-Key: your-cloud-key" \
  -H "X-Tenant-ID: your-tenant-id" \
  -H "Content-Type: application/json" \
  -d @policies-export.json

Step 4: Update SDK Configuration

# Before (self-hosted)
client = FulcrumClient(host="localhost:50051")

# After (cloud)
client = FulcrumClient(
    host="api.fulcrumlayer.io:443",
    api_key=os.environ["FULCRUM_API_KEY"],
    tenant_id=os.environ["FULCRUM_TENANT_ID"],
    use_tls=True
)
// Before (self-hosted)
const client = new FulcrumClient({ host: 'localhost:50051' });

// After (cloud)
const client = new FulcrumClient({
    host: 'api.fulcrumlayer.io:443',
    apiKey: process.env.FULCRUM_API_KEY,
    tenantId: process.env.FULCRUM_TENANT_ID,
    useTls: true
});

Step 5: Update MCP Configuration

{
  "mcpServers": {
    "fulcrum-governance": {
      "transport": "http",
      "url": "https://api.fulcrumlayer.io/mcp",
      "headers": {
        "X-API-Key": "your-cloud-key",
        "X-Tenant-ID": "your-tenant-id"
      }
    }
  }
}

Rollback Procedures

If migration fails and you need to rollback:

Application Rollback

Local Development:

# Stop current version
docker compose -f docker-compose.unified.yml down

# Pull previous version
docker compose -f docker-compose.unified.yml pull fulcrum-server:v0.1.x

# Start previous version
docker compose -f docker-compose.unified.yml up -d

Production (Railway):

# Use Railway rollback
railway rollback

Database Rollback

# Rollback last N migrations
docker compose -f docker-compose.unified.yml exec fulcrum-server \
  /app/migrate down N

# Or restore from backup
docker compose -f docker-compose.unified.yml exec fulcrum-postgres \
  psql -U fulcrum fulcrum < backup-20260201.sql

SDK Rollback

# Python
pip install fulcrum-governance==0.1.1

# TypeScript
npm install @fulcrum-governance/sdk@0.1.1

Troubleshooting Migrations

Migration Stuck

# Check for locks
docker compose -f docker-compose.unified.yml exec fulcrum-postgres \
  psql -U fulcrum -c "SELECT * FROM pg_locks WHERE NOT granted;"

# Kill blocking queries (carefully)
docker compose -f docker-compose.unified.yml exec fulcrum-postgres \
  psql -U fulcrum -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'idle in transaction';"

Schema Mismatch

If schema doesn't match expected state:

# Check current schema
docker compose -f docker-compose.unified.yml exec fulcrum-postgres \
  psql -U fulcrum -c "\dt"

# Force migration version (dangerous)
docker compose -f docker-compose.unified.yml exec fulcrum-server \
  /app/migrate force VERSION

Data Corruption

If data appears corrupted after migration: 1. Stop all services immediately 2. Restore from backup 3. Review migration logs 4. Contact support if needed


Getting Help

For migration assistance: - Review release notes - Check troubleshooting guide - Open GitHub issue - Enterprise: support@fulcrumlayer.io


Document created: 2026-02-01 Diataxis category: How-to Guide (task-oriented)