Prerequisites
Before you begin, ensure you have:- A PostgreSQL, MySQL, MariaDB, SQLite, or LibSQL database
- Terminal access
- Database connection credentials (if applicable)
Installation
Your First Migration
Let’s create a simple users table to demonstrate the complete migration workflow.Set Your Database URL
Geni uses the
DATABASE_URL environment variable to connect to your database. Choose your database type:For SQLite, Geni will automatically create the database file if it doesn’t exist. For other databases, you may need to create the database first using
geni create.Create the Database (Optional)
If you’re using PostgreSQL, MySQL, or MariaDB and need to create the database:
Generate Your First Migration
Create migration files for a users table:This creates two files in the
./migrations directory:YYYYMMDDHHMMSS_create_users_table.up.sql- Contains the forward migrationYYYYMMDDHHMMSS_create_users_table.down.sql- Contains the rollback migration
Write Your Migration SQL
Open the generated Now open the corresponding
.up.sql file and add your table creation SQL:.down.sql file and add the rollback SQL:Rollback (down)
The
.down.sql file should reverse everything that the .up.sql file does. This ensures you can safely rollback migrations if needed.Run the Migration
Apply your migration to the database:You should see output indicating the migration was successful. Geni will:
- Run your SQL inside a transaction (by default)
- Record the migration in the
schema_migrationstable - Generate a
schema.sqlfile with your current database schema
Testing Rollbacks
Let’s test rolling back the migration to ensure your.down.sql file works correctly.
Rollback the Migration
Rollback your most recent migration:This executes the SQL in your
.down.sql file, removing the users table and index.To rollback multiple migrations at once, use the -a flag:Verify the Rollback
Check the status again to confirm the migration was rolled back:Your migration should now show as pending.
Creating Additional Migrations
Let’s add a posts table that references the users table.Example: Adding a Posts Table
Example: Adding a Posts Table
Advanced Configuration
Customize Migration Folder Location
Customize Migration Folder Location
By default, Geni looks for migrations in
./migrations. To use a different location:Custom Migrations Table Name
Custom Migrations Table Name
Change the table where Geni tracks applied migrations:
Disable Schema Dumping
Disable Schema Dumping
By default, Geni creates a
schema.sql file after each migration. To disable this:Set Connection Timeout
Set Connection Timeout
If your database takes time to start up, adjust the wait timeout:
Common Workflows
Check Pending Migrations
Before deploying, see what migrations will run:
Run in CI/CD
In your deployment pipeline:
Rollback Bad Migration
Quickly revert the last migration:
Drop Database
Remove the entire database (be careful!):
What’s Next?
Now that you’ve mastered the basics, explore more advanced features:Database Support
Learn database-specific features and best practices
Transaction Control
Control when migrations run in transactions
CI/CD Integration
Automate migrations in your deployment pipeline
Library Usage
Use Geni programmatically in your Rust applications
Troubleshooting
Connection Errors
Connection Errors
If Geni can’t connect to your database:
- Verify your
DATABASE_URLis correct - Ensure your database is running
- Check firewall rules and network connectivity
- For LibSQL/Turso, verify your
DATABASE_TOKENis set
Migration File Not Found
Migration File Not Found
If Geni can’t find your migrations:
- Ensure migrations are in the correct folder (default:
./migrations) - Use
DATABASE_MIGRATIONS_FOLDERto specify a custom location - Check file naming:
TIMESTAMP_name.up.sqlandTIMESTAMP_name.down.sql
Transaction Errors
Transaction Errors
Some operations can’t run in transactions (like
CREATE INDEX CONCURRENTLY in PostgreSQL):- Add
-- transaction:noas the first line of your migration file - This disables transaction wrapping for that specific migration
Schema Dump Failures
Schema Dump Failures
If schema dumping fails:
- For MySQL, ensure
mysqldumpis installed - For MariaDB, ensure
mariadb-dumpis installed - Use
DATABASE_NO_DUMP_SCHEMA=trueto disable dumping - Consider using the slim Docker image if you don’t need dumps