Overview
The geni dump command exports your current database schema to a SQL file. This creates a snapshot of your database structure that can be used for documentation, version control, or disaster recovery.
Usage
DATABASE_URL = "<connection-string>" geni dump
Required Environment Variables
The database connection string. Format varies by database type. Examples:
PostgreSQL: postgres://user:password@localhost:5432/dbname?sslmode=disable
MySQL: mysql://root:password@localhost:3306/app
MariaDB: mariadb://root:password@localhost:3307/app
SQLite: sqlite://./database.sqlite
LibSQL: https://localhost:6000
Optional Environment Variables
Authentication token for LibSQL/Turso databases.
DATABASE_MIGRATIONS_FOLDER
string
default: "./migrations"
Directory where the schema file will be created.
DATABASE_MIGRATIONS_TABLE
string
default: "schema_migrations"
Name of the migrations tracking table.
DATABASE_SCHEMA_FILE
string
default: "schema.sql"
Name of the output schema file. The file will be created in the migrations folder.
Number of seconds to wait for the database to be ready.
How It Works
Connect to the database
Extract the complete database schema (tables, indexes, constraints, etc.)
Generate SQL statements that recreate the schema
Write the schema to a file in the migrations folder
Schema dumping happens automatically after geni up and geni down unless disabled with DATABASE_NO_DUMP_SCHEMA=true.
Database-Specific Requirements
PostgreSQL
✅ No external dependencies - Uses SQL queries to extract schema
DATABASE_URL = "postgres://localhost/app" geni dump
MySQL
⚠️ Requires mysqldump - Must be installed on the system
# Install mysqldump (usually included with MySQL client)
sudo apt-get install mysql-client
# Then run dump
DATABASE_URL = "mysql://root:password@localhost:3306/app" geni dump
MariaDB
⚠️ Requires mariadb-dump - Must be installed on the system
# Install mariadb-dump (usually included with MariaDB client)
sudo apt-get install mariadb-client
# Then run dump
DATABASE_URL = "mariadb://root:password@localhost:3307/app" geni dump
SQLite
✅ No external dependencies - Uses SQL queries to extract schema
DATABASE_URL = "sqlite://./database.sqlite" geni dump
LibSQL
✅ No external dependencies - Uses SQL queries to extract schema
DATABASE_URL = "https://localhost:6000" geni dump
Examples
PostgreSQL Dump
DATABASE_URL = "postgres://postgres:password@localhost:5432/app?sslmode=disable" geni dump
Output:
Generated file: ./migrations/schema.sql
Custom Schema File Name
DATABASE_URL = "postgres://localhost/app" \
DATABASE_SCHEMA_FILE= "current_schema.sql" \
geni dump
Generated file: ./migrations/current_schema.sql
Custom Migrations Folder
DATABASE_URL = "sqlite://./app.db" \
DATABASE_MIGRATIONS_FOLDER= "./db/migrations" \
geni dump
Generated file: ./db/migrations/schema.sql
MySQL with Custom Configuration
DATABASE_URL = "mysql://root:password@localhost:3306/app" \
DATABASE_SCHEMA_FILE= "mysql_schema.sql" \
DATABASE_MIGRATIONS_FOLDER= "./db" \
geni dump
Generated Schema File
The schema file contains SQL statements to recreate your database structure:
Example schema.sql (PostgreSQL):
-- Schema dump generated by Geni
-- Database: PostgreSQL
CREATE TABLE schema_migrations (
version VARCHAR ( 255 ) PRIMARY KEY
);
CREATE TABLE users (
id SERIAL PRIMARY KEY ,
email VARCHAR ( 255 ) NOT NULL UNIQUE ,
name VARCHAR ( 100 ),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE posts (
id SERIAL PRIMARY KEY ,
title VARCHAR ( 255 ) NOT NULL ,
content TEXT ,
user_id INTEGER REFERENCES users(id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_posts_user_id ON posts(user_id);
Use Cases
Version Control
Track schema changes in git:
# Dump schema
DATABASE_URL = "postgres://localhost/app" geni dump
# Commit to version control
git add migrations/schema.sql
git commit -m "Update schema after adding posts table"
git push
Documentation
Generate up-to-date schema documentation:
# Dump current schema
DATABASE_URL = " $PROD_DB " \
DATABASE_SCHEMA_FILE= "production_schema.sql" \
geni dump
# Use in documentation
cp migrations/production_schema.sql docs/database/
Disaster Recovery
Maintain schema snapshots:
# Create timestamped schema backup
DATABASE_URL = "postgres://localhost/app" \
DATABASE_SCHEMA_FILE= "schema_$( date +%Y%m%d_%H%M%S).sql" \
geni dump
Comparing Environments
Compare schemas across environments:
# Dump dev schema
DATABASE_URL = "sqlite://./dev.db" \
DATABASE_SCHEMA_FILE= "schema_dev.sql" \
geni dump
# Dump production schema
DATABASE_URL = " $PROD_DB " \
DATABASE_SCHEMA_FILE= "schema_prod.sql" \
geni dump
# Compare
diff migrations/schema_dev.sql migrations/schema_prod.sql
CI/CD Schema Validation
Validate schema in CI:
# In CI pipeline
DATABASE_URL = " $TEST_DB " geni up
DATABASE_URL = " $TEST_DB " geni dump
# Check if schema changed
if git diff --exit-code migrations/schema.sql ; then
echo "Schema unchanged"
else
echo "Schema modified - review changes"
git diff migrations/schema.sql
fi
Automatic Dumping
By default, Geni automatically dumps the schema after running migrations:
# Schema is dumped automatically after 'up'
DATABASE_URL = "postgres://localhost/app" geni up
# schema.sql is updated
# Schema is dumped automatically after 'down'
DATABASE_URL = "postgres://localhost/app" geni down
# schema.sql is updated
Disable Automatic Dumping
DATABASE_URL = "postgres://localhost/app" \
DATABASE_NO_DUMP_SCHEMA= "true" \
geni up
# schema.sql is NOT updated
Docker Usage
Standard Docker Image
docker run --rm -it --network=host \
-v "$( pwd )/migrations:/migrations" \
-e DATABASE_URL="postgres://localhost/app" \
ghcr.io/emilpriver/geni:latest dump
Slim Docker Image
The slim Docker image does not include mysqldump or mariadb-dump. Schema dumping will be skipped for MySQL and MariaDB when using the slim image.
# Slim image - no external dump tools
docker run --rm -it --network=host \
-v "$( pwd )/migrations:/migrations" \
-e DATABASE_URL="sqlite://./app.db" \
ghcr.io/emilpriver/geni:latest-slim dump
CI/CD Integration
GitHub Actions
- name : Run migrations and dump schema
run : |
DATABASE_URL="${{ secrets.DATABASE_URL }}" geni up
DATABASE_URL="${{ secrets.DATABASE_URL }}" geni dump
- name : Commit schema changes
run : |
git config user.name "GitHub Actions"
git config user.email "[email protected] "
git add migrations/schema.sql
git diff --quiet && git diff --staged --quiet || \
(git commit -m "Update schema.sql" && git push)
GitLab CI
dump-schema :
image : ghcr.io/emilpriver/geni:latest
script :
- geni dump
artifacts :
paths :
- migrations/schema.sql
expire_in : 30 days
variables :
DATABASE_URL : $DATABASE_URL
only :
- main
Error Handling
Missing mysqldump
Error: mysqldump command not found
Solution : Install the MySQL client:
# Ubuntu/Debian
sudo apt-get install mysql-client
# macOS
brew install mysql-client
# Alpine (Docker)
apk add mysql-client
Missing mariadb-dump
Error: mariadb-dump command not found
Solution : Install the MariaDB client:
# Ubuntu/Debian
sudo apt-get install mariadb-client
# Alpine (Docker)
apk add mariadb-client
Permission Denied
Error: Permission denied (os error 13)
Solution : Ensure you have write permissions to the migrations folder:
Best Practices
Version control : Always commit schema.sql to your repository
Regular dumps : Run geni dump after significant schema changes
Use in CI : Automate schema dumping in your CI/CD pipeline
Review changes : Check schema diffs before committing
Timestamp backups : Create timestamped schema files for archival
Compare environments : Use dumps to verify staging matches production
Document structure : Include schema files in your documentation
Slim images : Use the full Docker image if you need MySQL/MariaDB dumping
Automation Scripts
Automated Schema Backup
#!/bin/bash
set -e
DATABASE_URL = "postgres://localhost/app"
BACKUP_DIR = "./schema_backups"
mkdir -p " $BACKUP_DIR "
# Create timestamped backup
TIMESTAMP = $( date +%Y%m%d_%H%M%S )
DATABASE_URL = " $DATABASE_URL " \
DATABASE_SCHEMA_FILE= "schema_${ TIMESTAMP }.sql" \
DATABASE_MIGRATIONS_FOLDER= " $BACKUP_DIR " \
geni dump
echo "Schema backed up to: $BACKUP_DIR /schema_${ TIMESTAMP }.sql"
# Keep only last 30 backups
ls -t " $BACKUP_DIR "/schema_ * .sql | tail -n +31 | xargs -r rm
Make Commands
.PHONY : schema-dump
schema-dump :
@ echo "Dumping database schema..."
@ DATABASE_URL=" $( DATABASE_URL ) " geni dump
@ echo "Schema saved to migrations/schema.sql"
.PHONY : schema-backup
schema-backup :
@ mkdir -p schema_backups
@ DATABASE_URL=" $( DATABASE_URL ) " \
DATABASE_SCHEMA_FILE="schema_ $$ (date +%Y%m%d_%H%M%S).sql" \
DATABASE_MIGRATIONS_FOLDER="./schema_backups" \
geni dump
@ echo "Schema backup created"
Next Steps
Run Migrations Apply migrations with geni up
Check Status View migration status with geni status
Create Migration Create new migrations with geni new
Rollback Rollback migrations with geni down