Overview
Definable uses Alembic to manage database migrations. Alembic is an SQL migration tool for SQLAlchemy that provides:- Version control for database schemas
- Ability to upgrade and downgrade between versions
- Auto-generation of migrations based on model changes
- A flexible environment for migration script execution
001_create_base_tables.py
, 002_create_models_and_agents.py
).
Migration Workflow Visualization
Setup
The Alembic configuration is in the project root directory:alembic.ini
: Contains database connection information and Alembic settingsalembic/
: Directory containing migration scripts and environment configuration:env.py
: The Alembic environment setupscript.py.mako
: Template for generating migration filesversions/
: Directory containing migration scripts
Project Structure for Migrations
Creating a New Migration
Automatic Migration Generation
Alembic can automatically detect changes between your SQLAlchemy models and the current database schema to generate migrations:- Make changes to your SQLAlchemy models in the
src/models/
directory - Ensure the new model is imported in the models
__init__.py
file - Run the following command to generate a migration:
alembic/versions/
directory with a format like <revision_id>_description_of_changes.py
.
Automatic Migration Process
Manual Migration Creation
For more complex changes or to insert seed data, create a manual migration:upgrade()
and downgrade()
functions.
Migration File Format
Each migration file follows this structure:Migration Dependencies
Naming Convention
Following the projectβs convention, you should:- Prefix your migration file with the next sequential number
- Add a short descriptive name
- For example, if the latest migration is
010_create_upload_files.py
, name yours011_your_feature_name.py
Running Migrations
Upgrading the Database
To apply all pending migrations:Downgrading the Database
To downgrade to a previous revision:Migration State Flow
Checking Migration Status
To see the current database revision:Migration Examples
Creating a Table
Example Table Schema
Adding a Column
Column Addition Visualization
Modifying a Column
Adding a Foreign Key
Relationship Visualization
Inserting Seed Data
Best Practices
General Guidelines
- One migration per change: Create separate migrations for distinct changes to make them easier to understand and maintain
- Test migrations: Test both upgrade and downgrade paths before applying to production
- Be concise but descriptive: Use clear naming conventions that indicate what each migration does
- Comment your code: Add comments to complex migration logic to explain the purpose
Database Changes
- Non-destructive changes: Prefer adding over dropping where possible
- Nullable columns: When adding new columns to existing tables, make them nullable or provide a default value
- Data migrations: Separate schema changes from data migrations when possible
- Indexes: Add appropriate indexes for foreign keys and frequently queried columns
- Updated_at triggers: Add triggers for
updated_at
columns as demonstrated in the example migrations
Migration Decision Flow
SQL Execution
- Use SQLAlchemy operations: Prefer Alembicβs operation helpers (
op.*
) over raw SQL when possible - Transaction safety: Ensure your migrations are transaction-safe
- Idempotence: Make migrations idempotent where possible to avoid errors on reapplication
- Performance: Be mindful of migration performance on large tables; consider batch operations
Version Control
- Commit migrations: Always commit migration files to version control
- Do not edit applied migrations: Create new migrations rather than modifying existing ones that have been applied
Troubleshooting
Common Issues
- Autogeneration misses changes: Alembic canβt detect all types of changes. Always review auto-generated migrations.
- Migration conflicts: If multiple developers create migrations simultaneously, conflicts may occur. Coordinate migrations or adjust revision chains as needed.
- Database connection issues: Verify your database connection settings in
alembic.ini
. - SQLAlchemy model not detected: Ensure your model is imported in the models
__init__.py
file.
Troubleshooting Flow
Fixing a Failed Migration
If a migration fails midway:- Fix the issue in the migration script
- Run
alembic upgrade head
again, or specifically target the failed migration
- Manually fix the database state if necessary
- Mark the current revision:
alembic stamp <last_successful_revision>
- Then try upgrading again
Migration Workflow Summary
- Make changes to SQLAlchemy models
- Generate a migration with
alembic revision --autogenerate -m "description"
- Review and edit the generated migration file if necessary
- Rename the file to follow the sequential numbering convention
- Test the migration in a development environment
- Apply the migration with
alembic upgrade head
- Commit the migration file to version control