Pushing Schema Changes
Apply your schema changes to the database.
Last updated on
After modifying your schema, you need to push the changes to your database so the actual tables reflect your definitions.
Pushing is one of two ways to get a schema change into a database. The other is migrations, where changes are recorded as reviewable SQL files and applied deliberately. Push is the default; everything on this page describes a project that has not opted into migrations.
Dev and prod are separate branches
Typebase provisions two independent Neon branches inside the same project: one for dev and one for prod. Each branch has its own data, so you can iterate on your schema freely in development without risking your production data. Always test schema changes in dev before pushing to prod.
Pushing changes
Push to your dev database:
npx typebase-io-cli db dev pushPush to your prod database:
npx typebase-io-cli db prod pushYou don't need to run this manually every time. npx typebase-io-cli deploy dev and npx typebase-io-cli deploy prod automatically push your schema changes as part of the deployment process. So if you're deploying anyway, your database will always be in sync with your schema without any extra steps.
npx typebase-io-cli start does the same for a local run: every time you change something under typebase/db/, it pushes to the database you're running against before it restarts the server, so the server you're talking to always matches the schema you just edited.
That last part stops being true once a project uses migrations. In migrations mode deploy applies your pending
migrations instead of pushing, and refuses to deploy at all when your schema files hold changes no migration records.
Environment variables
The first time you push, the CLI provisions a Neon project (and the target branch if it doesn't exist yet) and stores the connection string in your project-root .env:
- In your project-root
.env: underDATABASE_URLfor prod andDATABASE_URL_DEVfor dev, so both connection strings can coexist in a single local file.
Provider environment variables are synced during npx typebase-io-cli deploy. On the provider, the deployed server always reads DATABASE_URL; each environment (dev, prod) gets its own value.
Destructive changes
If a schema change would destroy existing data (such as dropping a table or removing a column), the CLI will detect this and warn you before proceeding:
⚠ The following changes are destructive:
- Column "email" will be dropped from table "users"
? Are you sure you want to continue? (y/N)By default the CLI will not apply a destructive change until you answer that prompt. In production, treat these warnings carefully. Dropped columns and tables cannot be recovered.
Answering the prompt ahead of time
A pipeline has nobody at the keyboard, so each command that pushes takes a flag that answers the prompt in advance:
npx typebase-io-cli db dev push --skip-confirmationnpx typebase-io-cli deploy dev --skip-schema-changes-confirmationnpx typebase-io-cli start --skip-schema-changes-confirmationThe warnings are printed either way, so the log still records what was dropped. Nothing stops it, though, so reach for these only on a pipeline where the schema change has already been reviewed.
Viewing your data in Neon
Every Typebase database lives in a Neon project. You can log in to the Neon console to browse your data visually: inspect tables, run ad-hoc SELECT queries, check indexes, and switch between the dev and prod branches.
Don't edit your schema from the Neon UI. Your typebase/db/schema.ts is the source of truth. If you add a column, rename a table, or change a
constraint directly in Neon, the next npx typebase-io-cli db <target> push will detect the drift and try to "correct" it back to what schema.ts describes,
which usually means reverting your change, and in some cases failing the push outright.
The Neon UI is fine (and useful) for:
- Reading data and running queries
- Debugging a specific row or running a one-off data fix
- Exploring what the current schema actually looks like on the branch
For anything that changes the schema shape (tables, columns, types, constraints, indexes tied to your schema), edit schema.ts and run npx typebase-io-cli db dev push (or db prod push for production).
When push isn't enough
Push applies a change and leaves no record of it. There is no file to review in a pull request, no history to read, and no way to inspect the SQL before it runs. Anything the diff cannot express — a backfill, a rename it would turn into a drop-and-recreate — has nowhere to live, and two developers changing the schema on separate branches have nothing that notices the divergence.
Migrations exist for exactly those cases. You can adopt them on an existing project without recreating your databases:
npx typebase-io-cli db migrations initOnce a project has a typebase/db/migrations/ folder, the two modes are mutually exclusive: push refuses to run and points at db <target> migrate
instead.