Skip to content

SYSTEM

planetscale_rails gem

What it is

planetscale_rails is PlanetScale's Ruby gem that integrates Rails' ActiveRecord migration workflow with PlanetScale's schema-change lifecycle.

Introduced in Coutermarsh's 2023-03-20 post
"We've recently released the planetscale_rails gem. It contains a collection of Rake tasks that we have been using internally to manage the schema of our own Rails application." — a dogfooded-in-production tool open-sourced after the PlanetScale engineering team had used it against the app.planetscale.com Rails monolith.

Named again in the follow-up 2024 post as the migration executor used by PlanetScale's internal CI pull-request bot: "We use the planetscale_rails gem to run the migrations."

Role

The gem is the bridge between:

  • Rails' ActiveRecord migration convention — files under db/migrate/*.rb with up/down / change methods.
  • PlanetScale's deploy-request lifecycle — every production schema change runs via an isolated deploy request against a PlanetScale branch, not as a direct DDL execution at app-deploy time.

Without the gem, engineers would need to hand-translate ActiveRecord::Migration DDL into pscale CLI calls on a per-migration basis. The gem does this automatically, so the existing rake db:migrate mental model continues to work against a PlanetScale target.

Rake task surface

The 2023-03-20 post canonicalises the four Rake tasks the gem exposes (verbatim from post body):

rake psdb:migrate              # Migrate the database for current environment
rake psdb:rollback             # Rollback primary database for current environment
rake psdb:schema:load          # Load the current schema into the database
rake psdb:setup_pscale         # Setup a proxy to connect to PlanetScale
  • psdb:migrate — the ActiveRecord analog of db:migrate, but runs against a PlanetScale development branch (not production) via the .pscale.yml configuration file in the local directory. Production schema changes route through a deploy request + online DDL, not through this task.
  • psdb:rollback — rolls back the last migration on the current PlanetScale branch.
  • psdb:schema:load — loads the current schema.rb into the target database, typically for fresh-database initialisation.
  • psdb:setup_pscale — sets up a proxy connection to PlanetScale (wraps the pscale connect CLI under the hood).

The psdb: prefix deliberately separates PlanetScale-targeted runs from the standard db: prefix so both coexist — engineers can still run rails db:migrate against a local MySQL for development, then use rails psdb:migrate to promote the same migrations to a PlanetScale branch for deploy-request review.

Multi-database support

Rails 6+ multi-database apps are supported via :primary-style suffixes — e.g. rails psdb:migrate:primary, rails psdb:migrate:rollback. Composes with Rails's standard config/database.yml multi-db configuration.

.pscale.yml configuration

pscale branch switch my-feature --database my-db-name --create writes a .pscale.yml file to the local directory that records which PlanetScale branch the gem should target. psdb:migrate reads this file to determine the branch. Workflow implication: switching branches is a deliberate operator action (pscale branch switch), not a CLI flag on each migration run — the local working directory carries one active branch at a time.

schema_migrations table handling

The gem preserves Rails's standard schema_migrations tracking table without special handling — "nothing changes! Deploy requests will keep it up to date just like db:migrate does for you. When branching, the schema_migrations table gets copied across branches." Required setup: enable "Automatically copy migration data" in the database's PlanetScale dashboard settings.

Place in the architecture

┌─────────────────────────────────────────────┐
│ Rails app                                   │
│  └── db/migrate/20240101_add_column.rb      │
└─────────────────────────────────────────────┘
               │ (engineer runs `rake psdb:migrate`)
┌─────────────────────────────────────────────┐
│ planetscale_rails gem                       │
│  └── reads .pscale.yml                      │
│  └── runs migration via pscale proxy        │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ PlanetScale dev branch                      │
│  └── schema change applied (branch only)    │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ pscale deploy-request create                │
│  └── opens deploy request for review        │
└─────────────────────────────────────────────┘
               ▼ (PR + DR reviewed together)
               ▼ (DR ships first; then PR merges)
┌─────────────────────────────────────────────┐
│ Production branch                           │
│  └── shadow-table online migration          │
│  └── atomic cutover                         │
│  └── 30-min revert window                   │
└─────────────────────────────────────────────┘

For a Rails app using the PR-bot automation layer described in Coutermarsh's 2024 follow-up post, the gem is invoked by a GitHub Actions workflow when a migration file lands in a PR (rather than by an engineer at the console):

┌─────────────────────────────────────────────┐
│ GitHub Actions PR-bot                       │
│  └── detects db/migrate/*.rb change →       │
│      invokes planetscale_rails gem          │
└─────────────────────────────────────────────┘
┌─────────────────────────────────────────────┐
│ planetscale_rails gem                       │
│  └── runs migration against PlanetScale     │
│      branch; opens deploy request via       │
│      PlanetScale API                        │
└─────────────────────────────────────────────┘

Seen in

  • Canonical first-party-disclosure post (Mike Coutermarsh, 2023-03-20). Gem announced; four Rake tasks canonicalised verbatim; six-step manual workflow walked end to end; multi-database-Rails support named; .pscale.yml configuration disclosed; schema_migrations table handling clarified; ignored_columns-based column-drop recipe supplied; five-step rename-column recipe supplied; sys.schema_unused_indexes pre-drop verification query named; canonical expand-migrate- contract instantiation for Rails published. Positions the gem as the Rails equivalent of what the 2022 Laravel post positioned for PHP — a framework-specific bridge primitive that makes PlanetScale's [[patterns/branch-based-schema-change- workflow|branch-plus-deploy-request workflow]] feel native.

  • — Later naming (Coutermarsh, 2024). Used inside PlanetScale's own Rails API CI workflow as the migration executor that the GitHub Actions PR-bot invokes. Canonical quote: "We use the planetscale_rails gem to run the migrations." The 2024 post does not re-disclose the gem's internals; it references it as the tool-of-choice for the PR-bot auto-deploy-request pattern when the application framework is Rails.

Scope the sources do not cover

  • Gem internals: how it maps ActiveRecord::Migration DDL to pscale calls, which commands it supports beyond the four named, what Rails-version compatibility it has, whether change_table + reversible blocks are handled the same as raw up / down.
  • Non-migration schema changes: whether it handles ad-hoc ALTER TABLE invocations outside db/migrate/, ActiveRecord::Migrator programmatic invocation, or schema_dumper output.
  • Interaction with rails db:schema:load for fresh-database initialisation (the psdb:schema:load task is named but its semantics vs schema_migrations table are not fully elaborated).
  • Plain-MySQL usage: whether non-PlanetScale-customer Rails teams use it against plain MySQL as a safer migration executor, or whether it hard-depends on PlanetScale-specific API calls.
  • CI ergonomics: how the PR-bot sets up .pscale.yml in a CI environment, whether the gem can be configured via env vars instead of the YAML file, and how it handles missing or stale .pscale.yml state.
  • strong_migrations / active_record_doctor interaction: whether the gem composes with the Ruby ecosystem's parallel-evolved migration safety nets or replaces them.
Last updated · 542 distilled / 1,571 read