Skip to content

Database Migrations

Manage database schema changes with migrations.

Migration Files

migrations/
├── 002_multi_agent.sql
├── 003_agent_auth.sql
├── 004_workflow_executions.sql
├── 005_cloudflare_settings.sql
├── 006_browser_actions_types.sql
└── 007_puppeteer_action_types.sql

Initial Setup

Apply Main Schema

bash
npx wrangler d1 execute agents-dashboard --file=./schema.sql

Apply All Migrations

bash
# Apply in order
npx wrangler d1 execute agents-dashboard --file=./migrations/002_multi_agent.sql
npx wrangler d1 execute agents-dashboard --file=./migrations/003_agent_auth.sql
npx wrangler d1 execute agents-dashboard --file=./migrations/004_workflow_executions.sql
npx wrangler d1 execute agents-dashboard --file=./migrations/005_cloudflare_settings.sql
npx wrangler d1 execute agents-dashboard --file=./migrations/006_browser_actions_types.sql
npx wrangler d1 execute agents-dashboard --file=./migrations/007_puppeteer_action_types.sql

Local Development

bash
# Apply to local database
npx wrangler d1 execute agents-dashboard --local --file=./schema.sql
npx wrangler d1 execute agents-dashboard --local --file=./migrations/002_multi_agent.sql
# ... continue for all migrations

Creating Migrations

1. Create Migration File

bash
touch migrations/008_new_feature.sql

2. Write Migration SQL

sql
-- migrations/008_new_feature.sql

-- Add new column
ALTER TABLE agents ADD COLUMN new_field TEXT;

-- Create new table
CREATE TABLE IF NOT EXISTS new_table (
  id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(4)))),
  agent_id TEXT NOT NULL REFERENCES agents(id),
  data TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- Create index
CREATE INDEX IF NOT EXISTS idx_new_table_agent
ON new_table(agent_id);

3. Test Locally

bash
npx wrangler d1 execute agents-dashboard --local --file=./migrations/008_new_feature.sql

4. Apply to Production

bash
npx wrangler d1 execute agents-dashboard --file=./migrations/008_new_feature.sql

Migration Patterns

Add Column

sql
ALTER TABLE agents ADD COLUMN new_field TEXT;
ALTER TABLE agents ADD COLUMN count INTEGER DEFAULT 0;

Add Table

sql
CREATE TABLE IF NOT EXISTS new_table (
  id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(4)))),
  name TEXT NOT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Add Index

sql
CREATE INDEX IF NOT EXISTS idx_table_column ON table_name(column_name);
CREATE INDEX IF NOT EXISTS idx_table_multi ON table_name(col1, col2);

Add Foreign Key

SQLite doesn't support ADD CONSTRAINT. Recreate table:

sql
-- Create new table with constraint
CREATE TABLE new_table_temp (
  id TEXT PRIMARY KEY,
  agent_id TEXT NOT NULL REFERENCES agents(id),
  data TEXT
);

-- Copy data
INSERT INTO new_table_temp SELECT * FROM new_table;

-- Drop old table
DROP TABLE new_table;

-- Rename
ALTER TABLE new_table_temp RENAME TO new_table;

Add Default Value

sql
ALTER TABLE agents ADD COLUMN status TEXT DEFAULT 'active';

Migration Best Practices

1. Always Use IF NOT EXISTS

sql
CREATE TABLE IF NOT EXISTS new_table (...);
CREATE INDEX IF NOT EXISTS idx_name ON table(column);

2. Make Migrations Idempotent

Safe to run multiple times:

sql
-- Safe
CREATE TABLE IF NOT EXISTS users (...);

-- Not safe (will fail on re-run)
CREATE TABLE users (...);

3. Keep Migrations Small

One feature per migration:

sql
-- migrations/008_add_user_preferences.sql
ALTER TABLE users ADD COLUMN preferences TEXT;

4. Name Migrations Descriptively

008_add_user_preferences.sql
009_create_audit_log.sql
010_add_workflow_tags.sql

5. Test Before Production

bash
# Test locally first
npx wrangler d1 execute agents-dashboard --local --file=./migrations/008_new.sql

# Verify
npx wrangler d1 execute agents-dashboard --local --command "SELECT * FROM sqlite_master WHERE type='table'"

Rollback Strategy

D1 doesn't support transactions for DDL. Create reverse migrations:

Forward Migration

sql
-- migrations/008_add_feature.sql
ALTER TABLE agents ADD COLUMN new_field TEXT;

Rollback Migration

sql
-- rollbacks/008_remove_feature.sql
-- Note: SQLite doesn't support DROP COLUMN easily
-- May need to recreate table

Schema Inspection

List Tables

bash
npx wrangler d1 execute agents-dashboard \
  --command "SELECT name FROM sqlite_master WHERE type='table'"

Describe Table

bash
npx wrangler d1 execute agents-dashboard \
  --command "PRAGMA table_info(agents)"

List Indexes

bash
npx wrangler d1 execute agents-dashboard \
  --command "SELECT name FROM sqlite_master WHERE type='index'"

CI/CD Migrations

GitHub Actions

yaml
- name: Apply migrations
  run: |
    npx wrangler d1 execute agents-dashboard --file=./schema.sql
    for f in migrations/*.sql; do
      npx wrangler d1 execute agents-dashboard --file="$f"
    done
  env:
    CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}

Migration Tracking

Consider a migrations table:

sql
CREATE TABLE IF NOT EXISTS _migrations (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL UNIQUE,
  applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Apply with tracking:

sql
-- At end of migration
INSERT OR IGNORE INTO _migrations (name) VALUES ('008_add_feature');

Troubleshooting

Migration Failed

  1. Check syntax errors
  2. Verify table/column exists
  3. Check constraints
bash
# Get error details
npx wrangler d1 execute agents-dashboard --command "SELECT * FROM agents LIMIT 1"

Duplicate Column

Error: duplicate column name: new_field

Already applied. Skip or check IF NOT EXISTS.

Foreign Key Violation

Error: FOREIGN KEY constraint failed

Ensure referenced row exists or set ON DELETE behavior.

Released under the MIT License.