npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@indiekitai/pg-safe-migrate

v1.0.1

Published

Catch unsafe PostgreSQL migrations before they reach production. The JS/TS equivalent of Ruby's strong_migrations.

Readme

@indiekitai/pg-safe-migrate

Catch unsafe PostgreSQL migrations before they reach production.

The JS/TypeScript equivalent of Ruby's strong_migrations (⭐ 4k). Zero other JS alternatives exist.

npx @indiekitai/pg-safe-migrate check ./migrations/001_add_index.sql
Checking: migrations/001_add_index.sql

  ✗ [DANGER] Create Index Without Concurrently (line 1)
    CREATE INDEX idx_users_email ON users (email);
    ↳ CREATE INDEX without CONCURRENTLY locks the table for reads and writes during index creation.
    ↳ Fix: Use CREATE INDEX CONCURRENTLY to build the index without locking.

Summary: 1 danger, 0 warnings, 0 info — NOT SAFE

Install

npm install -g @indiekitai/pg-safe-migrate
# or use directly:
npx @indiekitai/pg-safe-migrate check migration.sql

Usage

# Check a single migration file
pg-safe-migrate check migration.sql

# Check all .sql files in a directory
pg-safe-migrate check ./migrations/

# JSON output (for CI pipelines)
pg-safe-migrate check migration.sql --json

# List all available checks
pg-safe-migrate list-checks

Exit codes: 0 = safe, 1 = DANGER found, 2 = WARNING found (no dangers)

CI Integration

# GitHub Actions
- name: Check migrations
  run: npx @indiekitai/pg-safe-migrate check ./migrations/ --json

All 15 Checks

🔴 DANGER — Will cause downtime or data loss

| Check | Issue | Safe Alternative | |-------|-------|-----------------| | create_index_without_concurrently | Locks table during index build | CREATE INDEX CONCURRENTLY | | add_column_not_null_without_default | Table rewrite in older PG | Add nullable, backfill, add NOT NULL | | alter_column_type | Rewrites entire table | New column → backfill → rename | | add_foreign_key_without_not_valid | Full scan + lock | Add NOT VALID, then VALIDATE CONSTRAINT | | add_unique_constraint | Full scan + lock | CREATE UNIQUE INDEX CONCURRENTLYUSING INDEX | | set_not_null | Full table scan | CHECK CONSTRAINT NOT VALID pattern | | drop_table | Irreversible | Remove app code first | | truncate_table | ACCESS EXCLUSIVE lock | Batched DELETE |

🟡 WARNING — Risky, may cause issues

| Check | Issue | Safe Alternative | |-------|-------|-----------------| | rename_column | Breaks ORM caching | Dual-write pattern | | rename_table | Breaks all queries | Transitional view | | drop_column | ORM attribute caching | Ignore in app code first | | add_check_constraint_without_not_valid | Full table scan | Add NOT VALID, validate later |

🔵 INFO — Best practices

| Check | Issue | |-------|-------| | multiple_operations | >3 ALTER TABLE statements, hard to roll back | | backfill_without_where | UPDATE without WHERE can timeout | | index_on_many_columns | 4+ column index has diminishing returns |

MCP Server (for Claude / Cursor)

After installing globally (npm install -g @indiekitai/pg-safe-migrate):

{
  "mcpServers": {
    "pg-safe-migrate": {
      "command": "pg-safe-migrate-mcp"
    }
  }
}

Or without global install:

{
  "mcpServers": {
    "pg-safe-migrate": {
      "command": "npx",
      "args": ["--package", "@indiekitai/pg-safe-migrate", "pg-safe-migrate-mcp"]
    }
  }
}

Tools available:

  • check_migration(sql) — check SQL string for issues
  • list_checks() — list all checks
  • explain_check(checkName) — explain a specific check

Programmatic Usage

import { checkMigration } from "@indiekitai/pg-safe-migrate";

const result = checkMigration(`
  CREATE INDEX idx_users_email ON users (email);
`);

console.log(result.safe);           // false
console.log(result.summary);        // { danger: 1, warning: 0, info: 0 }
console.log(result.issues[0].check); // "create_index_without_concurrently"

Why This Exists

Ruby has strong_migrations. Python has nothing. JavaScript has nothing. Until now.

If you're running PostgreSQL with Node.js (Prisma, Drizzle, node-pg-migrate, raw SQL), this tool gives you the same safety net Rails developers have had for years.


Part of the IndieKit PostgreSQL toolchain: pg-inspect · pg-diff · pg-top · pg-safe-migrate · pg-dash