Skip to main content

Overview

The geni status command displays which migrations are pending (not yet applied) to your database. This helps you understand what changes will be made before running geni up.

Usage

DATABASE_URL="<connection-string>" geni status

With Verbose Flag

DATABASE_URL="<connection-string>" geni status --verbose
DATABASE_URL="<connection-string>" geni status -v

Flags

--verbose
boolean
default:"false"
Include the full SQL content of pending migrations in the output.Aliases: -vDefault behavior: Only shows migration timestamps/namesWith flag: Shows timestamps/names and complete SQL content

Required Environment Variables

DATABASE_URL
string
required
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

DATABASE_TOKEN
string
default:"none"
Authentication token for LibSQL/Turso databases.
DATABASE_MIGRATIONS_FOLDER
string
default:"./migrations"
Path to the directory containing migration files.
DATABASE_MIGRATIONS_TABLE
string
default:"schema_migrations"
Name of the table used to track applied migrations.
DATABASE_SCHEMA_FILE
string
default:"schema.sql"
Filename for the database schema file.
DATABASE_WAIT_TIMEOUT
number
default:"30"
Number of seconds to wait for the database to be ready.

How It Works

  1. Connect to the database
  2. Read the migrations tracking table to get applied migrations
  3. Scan the migrations folder for .up.sql files
  4. Compare local migration files with applied migrations
  5. Display migrations that exist locally but not in the database

Examples

Basic Status Check

DATABASE_URL="postgres://postgres:password@localhost:5432/app?sslmode=disable" geni status
Output (with pending migrations):
Pending 1709395200
Pending 1709395245
Pending 1709395300
Output (no pending migrations):
(no output - all migrations are applied)

Verbose Status

Show the complete SQL content of pending migrations:
DATABASE_URL="postgres://localhost/app" geni status --verbose
Output:
Pending migration 1709395200: 
 CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Pending migration 1709395245:
 ALTER TABLE users ADD COLUMN name VARCHAR(100);

Pending migration 1709395300:
 CREATE INDEX idx_users_email ON users(email);

SQLite Example

DATABASE_URL="sqlite://./database.sqlite" geni status

MySQL Example

DATABASE_URL="mysql://root:password@localhost:3306/app" geni status -v

LibSQL/Turso Example

DATABASE_URL="https://my-database-user.turso.io" \
DATABASE_TOKEN="eyJhbGc..." \
geni status

Custom Configuration

DATABASE_URL="postgres://localhost/mydb" \
DATABASE_MIGRATIONS_FOLDER="./db/migrations" \
DATABASE_MIGRATIONS_TABLE="my_migrations" \
geni status

Understanding the Output

Pending Migrations

Each line starting with “Pending” indicates a migration that exists in your migrations folder but hasn’t been applied to the database:
Pending 1709395200
Pending 1709395245
The number is the Unix timestamp from the migration filename.

No Output

If geni status produces no output, your database is up to date:
$ DATABASE_URL="postgres://localhost/app" geni status
$ echo $?
0

Verbose Mode Details

With --verbose, you see:
  1. Migration identifier: The timestamp/name
  2. SQL content: The complete contents of the .up.sql file
Pending migration 1709395200:
 CREATE TABLE users (
     id SERIAL PRIMARY KEY,
     email VARCHAR(255) NOT NULL UNIQUE
 );

Use Cases

Pre-Deployment Check

Verify what migrations will run before deploying:
# Check staging
DATABASE_URL="$STAGING_DB" geni status

# Check production
DATABASE_URL="$PROD_DB" geni status

Development Workflow

Check migration status during development:
# After pulling changes from git
git pull
DATABASE_URL="sqlite://./dev.db" geni status

# See what changed
DATABASE_URL="sqlite://./dev.db" geni status -v

CI/CD Validation

Validate migrations in CI before applying them:
# In CI script
if DATABASE_URL="$TEST_DB" geni status | grep -q "Pending"; then
  echo "Pending migrations found, running tests..."
  DATABASE_URL="$TEST_DB" geni up
  npm test
else
  echo "No pending migrations"
fi

Code Review

Review pending migrations with verbose output:
DATABASE_URL="postgres://localhost/review-db" geni status --verbose > pending_migrations.txt

Comparing Environments

Check migration status across different environments:
# Development
echo "=== Development ==="
DATABASE_URL="sqlite://./dev.db" geni status

# Staging
echo "=== Staging ==="
DATABASE_URL="$STAGING_DB" geni status

# Production
echo "=== Production ==="
DATABASE_URL="$PROD_DB" geni status

Integration Examples

Bash Script

#!/bin/bash
set -e

echo "Checking migration status..."
DATABASE_URL="$DATABASE_URL" geni status

read -p "Apply pending migrations? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    DATABASE_URL="$DATABASE_URL" geni up
    echo "Migrations applied successfully!"
fi

Make Command

.PHONY: migration-status
migration-status:
	@echo "Migration Status:"
	@DATABASE_URL="$(DATABASE_URL)" geni status

.PHONY: migration-status-verbose
migration-status-verbose:
	@DATABASE_URL="$(DATABASE_URL)" geni status --verbose

Docker

docker run --rm -it --network=host \
  -v "$(pwd)/migrations:/migrations" \
  -e DATABASE_URL="postgres://localhost/app" \
  ghcr.io/emilpriver/geni:latest status -v

CI/CD Integration

GitHub Actions

- name: Check migration status
  run: |
    DATABASE_URL="${{ secrets.DATABASE_URL }}" geni status
    DATABASE_URL="${{ secrets.DATABASE_URL }}" geni status -v > migration_plan.txt
  
- name: Upload migration plan
  uses: actions/upload-artifact@v3
  with:
    name: migration-plan
    path: migration_plan.txt

GitLab CI

check-migrations:
  image: ghcr.io/emilpriver/geni:latest
  script:
    - geni status
    - geni status --verbose
  variables:
    DATABASE_URL: $DATABASE_URL
  only:
    - merge_requests

Error Handling

No Migrations Folder

Couldn't read migration folder: No such file or directory
Solution: Ensure the migrations folder exists or set DATABASE_MIGRATIONS_FOLDER correctly.

Connection Failed

No database url found, please set the DATABASE_URL environment variable
Solution: Set the DATABASE_URL environment variable.

Migration Table Doesn’t Exist

If the migrations tracking table doesn’t exist, geni status will create it automatically and show all migrations as pending.

Interpreting Results

All Migrations Applied

$ geni status
$ # No output = database is up to date

Some Migrations Pending

$ geni status
Pending 1709395200
Pending 1709395245
These migrations need to be applied with geni up.

Database Behind Local

If you see many pending migrations, your database might be significantly behind:
$ geni status
Pending 1709395000
Pending 1709395100
Pending 1709395200
Pending 1709395300
Pending 1709395400
# Database is 5 migrations behind

Best Practices

  • Check before applying: Always run geni status before geni up
  • Use in CI/CD: Integrate status checks into your deployment pipeline
  • Review with verbose: Use -v to review SQL before applying in production
  • Document in PRs: Include geni status -v output in pull requests
  • Compare environments: Regularly check that staging and production are in sync
  • Monitor drift: If environments show different pending migrations, investigate

Next Steps

Apply Migrations

Run pending migrations with geni up

Create Migration

Create new migrations with geni new

Rollback

Rollback migrations with geni down

Dump Schema

Export database schema with geni dump

Build docs developers (and LLMs) love