Skip to main content
This guide walks through the complete pgtofu workflow from an existing database to a fully declarative schema management setup.

Initial Setup

1. Extract Current Schema

Start by extracting your current database schema:
This creates a JSON snapshot of your database’s current state.

2. Create Schema Directory

Create a directory structure for your desired schema:

3. Convert JSON to SQL Files

Review the extracted JSON and create corresponding SQL files. You can either: Option A: Start from scratch - Write new SQL files based on the JSON Option B: Use the JSON as reference - The JSON shows exactly what exists:

Example: Creating Schema Files

schema/extensions/extensions.sql:
schema/tables/users.sql:
schema/tables/orders.sql:
schema/functions/triggers.sql:

Daily Workflow

Making Schema Changes

When you need to modify your schema:

1. Update SQL Files

Edit your schema files directly:

2. Re-extract Current Schema

Get the latest database state:

3. Preview Changes

See what migrations will be generated:
Output:

4. Generate Migrations

Create migration files:

5. Review Migrations

Always review generated migrations before applying:

6. Apply Migrations

7. Commit Changes

Complete Example: Adding a Feature

Let’s add a complete feature: user comments on orders.

Step 1: Add New Table

schema/tables/order_comments.sql:
schema/views/order_details.sql:

Step 3: Generate and Apply

Handling Breaking Changes

Dropping a Column

When you need to remove a column:
  1. Remove from SQL file - Delete the column definition
  2. Preview - pgtofu will show a BREAKING change
  3. Verify - Ensure the column is truly unused
  4. Generate and review - Check the migration carefully
The generated migration will include a warning:

Changing Column Types

For type changes that require data migration:
  1. Add new column with desired type
  2. Migrate data with custom script
  3. Remove old column
  4. Rename new column (optional)

Best Practices

  • Always commit schema files and migrations together
  • Use meaningful commit messages describing the change
  • Review migrations in pull requests
  • One file per table (with its indexes)
  • Group related views and functions
  • Separate extensions into their own file
  • Always preview before generating
  • Review generated SQL before applying
  • Test migrations on non-production first
  • Re-extract before generating new migrations
  • Communicate breaking changes to team
  • Consider feature flags for gradual rollouts

See Also