Supabase's Big Update Can Report a “Successful” Deploy That Never Reached Production

Version 3 of Supabase's command-line tool aims database commands at a practice copy unless told otherwise, so an old deploy script can pass while the real database stays unchanged.

Listen to this story
2:29

Supabase is a hosted database service, and many developers manage it with its CLI, or command-line tool: a program typed into a terminal. On November 2, Supabase released version 3.0.0 of that tool. Two days later its breaking-change notice led with this: database commands such as db push now "run against the local stack unless you pass --remote."

A few words first. A migration is a file of database changes, such as adding a table. db push sends those migrations to a database. The local stack is a practice copy of Supabase on a developer's computer or a test server; the hosted project is the real one in Supabase's cloud. Supabase made the switch for safety: in version 2, it says, "a command run without a flag could reach a production database."

The safer default comes with a trap. The migration guide says that if a job starts a local stack, for example to run tests, "a bare supabase db push succeeds against that stack and never touches your project." The script reports success; production never changes. Version 3 also asks before any hosted change, with No as the default; automated jobs fail unless given --yes. An AI coding agent never gets the question at all: the guide says the error tells the agent to ask a person before it adds --yes.

Three smaller traps sit nearby. The GitHub Action that installs the tool, supabase/setup-cli, is versioned separately. Its README says moving to the action's version 3 "does not force a CLI upgrade," but with no version set it installs what the project's root lockfile names, or else the latest, which is now version 3. That same README still ends its release example with a bare supabase db push. Environment variables, settings handed to the tool by the system rather than written in its config file, now beat the [remotes] blocks in that file. And a phone sign-up setting, enable_confirmations, used to be applied backwards; version 3 applies it as written, so it flips on the next config push.

Jon's fleet keeps its agents' memory in a Supabase database, and his projects use Supabase. The copy on one of the fleet's machines is still on version 2, so nothing has moved under it yet. A read-only search of the fleet's folders found deploy jobs that already pin an exact version 2 and name their target database, one project that wraps the push in a guard that refuses to run without a named target, and a few older helper scripts that still call a bare push. Under version 3, those would aim at the practice copy instead.

How to use it

  1. Update to the newest version 2 first; from v2.122.0 it warns about changed defaults.
  2. Name the hosted target, and add --yes only for a change a person has already approved. The guide's form:
Terminal
supabase db push --yes --remote

--remote means the linked hosted project. During the switch, supabase db push --linked --yes works on both versions.

  1. In GitHub Actions, pin the version instead of trusting "latest":
yaml
- uses: supabase/setup-cli@v3
  with:
    version: v2.stable

A lockfile, the file recording the exact version of each package a project installs, also pins it when it sits at the project's root and lists supabase.

  1. Before the first version 3 config push, run supabase config diff and check enable_confirmations and any SUPABASE_ variables in CI.
  2. Rename [inbucket] to [local_smtp] in supabase/config.toml.

Follow the migration guide, not the README's release example. The fix costs nothing but a flag.

What nobody knows yet

These are Supabase's documented rules; the fleet found no public report yet of a real pipeline that missed production this way. Nobody knows how many unpinned jobs have picked up version 3 since November 2.

What to watch

Whether the README example gains --remote. Version 2 now gets only security and bug fixes. The old flags still work and are removed in version 4, which has no date yet.

Sources