Migrating from Xata to Layerbase
Short version: the new Xata runs vanilla Postgres, so a migration is a pg_dump into a psql, or the same thing done for you by the wizard at layerbase.com/migrate/xata. Schema, data, sequences, and indexes all copy. Xata branches, pgroll migration history, and anonymization rules do not, because none of them live inside the database. The one detail that decides whether the copy works at all is which hostname you paste: the -rw endpoint, never the -pooler one.
If you are still deciding whether to move, Xata alternatives is the comparison. This post assumes you have decided and want it done.
Contents
- What moves and what does not
- The migration, step by step
- The connection string gotcha
- Rebuilding your branches
- Pointing your app at the new database
- The manual path
- FAQ
What moves and what does not
Xata's rebuild put unmodified Postgres at the center, which is the best possible news for a migration. There is no Xata-specific storage format to unpack and no proprietary types to translate.
Copies across:
- Every table, column, constraint, and index in every schema you own
- Data, including large tables, in one pass
- Sequences and their current values, so your next
INSERTdoes not collide - Views, functions, and triggers written in plain SQL or PL/pgSQL
- Extensions that Layerbase Postgres supports, such as
pgcrypto,uuid-ossp,pg_trgm, andpgvector. An extension we do not ship fails atCREATE EXTENSIONand the error names it, so you find out at restore time rather than at runtime
Stays behind:
- Branches. A Xata branch is a copy-on-write child at the storage layer, not a thing inside the database. The migration copies one branch. Pick the one you want to be
mainon the other side, usually the branch your production app points at, and recreate the others with Layerbase branching afterwards. - pgroll migration history. pgroll keeps its state in a
pgrollschema and manages expand-and-contract migrations on your behalf. The tables it created for you copy fine, because they are ordinary tables. The migration history itself is only useful to pgroll, and you should not carry it into a database pgroll is not managing. - Anonymization rules. Xata's PII scrubbing runs when a branch is created. It is configuration on the platform, not data in the database, so it does not travel and there is no equivalent on the other side.
- Xata Lite APIs. If your app was on the original platform, using the record, search, or files APIs through the SDK, those have no equivalent anywhere. On the rebuilt platform the data behind them is plain Postgres tables and comes across with everything else. On the old platform you need to export through the old SDK while you still can, because the endpoint has already started returning 410.
The migration, step by step
Step 1: Get the right connection string
In the Xata dashboard, open the branch you want to migrate and copy its connection string. It looks like this:
postgresql://user:pass@<branch-id>-rw.us-east-1.xata.sh:5432/postgresThe -rw in the hostname matters. More on that in the next section.
Step 2: Start the migration
Go to layerbase.com/migrate/xata and sign in. The create flow opens with Migrating from another platform and Xata already selected. Paste the connection string, give the new database a name, and start it.
The wizard connects once, reads the schema and the data, and disconnects. Nothing is written back to your Xata branch, and it keeps serving your app throughout. There is no ongoing sync, so treat this as a point-in-time copy and plan a cutover rather than running both for a week.
Step 3: Let it copy
The dashboard shows progress per table. A few hundred megabytes takes a minute or two. A few gigabytes takes a few minutes, mostly bounded by how fast Xata hands the bytes out.
Step 4: Grab the connection string
When it finishes, the new database's Quick Connect panel shows the string:
postgresql://layerbase:<password>@<host>.cloud.layerbase.dev:5432/appdb?sslmode=requirePooled and direct endpoints are both listed. Use the direct one for migrations and admin work and the pooled one for application traffic, the same split you were already making on Xata.
The connection string gotcha
Xata gives every branch two hostnames. <branch-id>-rw.<region>.xata.sh is the direct Postgres endpoint. Swap -rw for -pooler and you get PgBouncer in transaction mode in front of the same database.
Xata's own pooler announcement lists what does not work through the pooler: LISTEN/NOTIFY, session-level advisory locks, temporary tables and SET, long-running analytics, and "schema migrations (pg_dump/pg_restore use SET statements)." That last one is the migration. A transaction-mode pooler hands connections back after every transaction, and pg_dump holds a single session open for the whole copy with a consistent snapshot pinned to it. Through the pooler the dump either fails outright or produces something you should not trust.
So: paste the -rw string. If you paste -pooler by mistake, the wizard swaps it for the -rw host before the copy starts and says so, the same treatment a Neon pooler string gets. The manual pg_dump path has no such net, so check the hostname there.
Rebuilding your branches
This is the part of a Xata migration people worry about, and it is less work than it sounds.
Layerbase branching is also copy-on-write at the storage layer, so a branch of the migrated database comes up in seconds with the data as of now, and only writes diverge. The counts per plan are 1 branch per database on Free, 3 on Solo, and 10 on Pro.
To recreate a preview-per-pull-request workflow, connect the database to your Vercel project or GitHub repository from its Branches tab. A pull request gets its own branch with its own connection string injected into the preview environment, and the branch is deleted when the PR closes. The Vercel preview branches post walks through that end to end.
What you do not get back is anonymization. If your Xata branches were scrubbed of PII on creation, your Layerbase branches contain what production contains. Decide before you wire previews up whether that is acceptable for your team, and if it is not, that is a reason to stay on Xata rather than a thing to work around.
If you want a copy on your own machine for local development, lbase cloud clone <db> pulls it into a local Postgres with one command.
Pointing your app at the new database
Swap the environment variable and redeploy. Nothing else in the app changes, because both sides are Postgres.
# Vercel
vercel env add DATABASE_URL production
# paste the Layerbase string when prompted, then redeploy
# Anywhere else
export DATABASE_URL="postgresql://layerbase:<password>@<host>.cloud.layerbase.dev:5432/appdb?sslmode=require"If you were using the Xata -pooler endpoint in production, use the Layerbase pooled endpoint in its place. If you were using -rw directly, use the direct one. Same rule, same reasons.
Before you delete the Xata branch, run the same count on both sides:
SELECT relname, n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC
LIMIT 20;Then leave the Xata branch alone until your trial or billing period ends. It costs nothing while nothing is connected to it, and a week of insurance is cheap.
The manual path
If you would rather run the copy yourself, it is one pipe. Create an empty Postgres on Layerbase first so you have the destination string.
pg_dump "postgresql://user:pass@<branch-id>-rw.us-east-1.xata.sh:5432/postgres" \
--no-owner --no-acl \
| psql "postgresql://layerbase:<password>@<host>.cloud.layerbase.dev:5432/appdb?sslmode=require"--no-owner --no-acl strips the Xata role names out of the dump so the restore does not fail trying to ALTER ... OWNER TO a user that does not exist on the other side. Everything you own ends up owned by the layerbase user.
If the dump complains about a pgroll schema you do not want to carry, exclude it:
pg_dump "postgresql://...-rw.us-east-1.xata.sh:5432/postgres" \
--no-owner --no-acl \
--exclude-schema=pgroll \
| psql "postgresql://layerbase:...@<host>.cloud.layerbase.dev:5432/appdb?sslmode=require"For a database large enough that a single pipe makes you nervous, dump to a directory-format archive with -Fd -j 4 and restore with pg_restore -j 4. Same flags, parallel workers, resumable per table.
FAQ
How much downtime does this take?
The copy itself needs none, because Xata keeps serving your app while it is read. The cutover is the redeploy after you change DATABASE_URL, which is however long your deploy takes. Writes that land on Xata between the copy starting and the cutover are not included, so for an exact cutover pause writes briefly or re-run the copy into a fresh database at switch time.
Which Xata endpoint do I paste?
The -rw one. The -pooler endpoint is PgBouncer in transaction mode and Xata documents that pg_dump and pg_restore do not work through it. Paste the -rw string into the wizard, or paste -pooler and let the wizard swap it for -rw before the copy starts. The manual pg_dump path does not rewrite anything, so there the hostname has to be right before you start.
Do my Xata branches come across?
No. A branch is a storage-layer object, not something inside the database, and the migration copies exactly one branch. Migrate the one your production app uses, then recreate the others with Layerbase branching, which is also copy-on-write and comes up in seconds.
What about pgroll?
The tables pgroll created for you are ordinary tables and copy normally. Its migration history lives in a pgroll schema that is only meaningful to pgroll. Exclude it with --exclude-schema=pgroll if you are running the dump yourself, and run future migrations with whatever your ORM uses.
Does anonymization carry over?
No. Xata scrubs PII when it creates a branch, using rules configured on the platform. Layerbase branches contain what their parent contains. If anonymized branches are a compliance requirement for your team, that is a real reason to stay on Xata.
I was on the old Xata, with the records and search SDK. Does this apply?
Only partly. The original platform, later called Xata Lite, exposed records, search, and files through its own SDK, and its site now returns 410. If you still have access, export your data through the SDK into plain tables or CSV first, then load that into Postgres. If your project was already on the rebuilt platform, the data is Postgres tables and everything above applies as written.
Wrapping up
Xata built the new product on unmodified Postgres, which means the way out is the standard way out: one dump, one restore, one environment variable. The only trap is the pooler hostname, and now you know about it. Branches get rebuilt on the other side in seconds. Anonymization does not, and if that matters, stay.
Start at layerbase.com/migrate/xata, or create an empty Postgres and run the pipe yourself.
Keep reading
- Xata alternatives: the free tier is gone, and the new product is a branching competitorXata rebuilt itself as a copy-on-write Postgres branching platform and retired the 15 GB free tier along the way. Cloud now starts at $0.012 an hour plus storage with a 14-day trial. Here is what that costs a side project, what the new Xata is genuinely good at, and where to land if the free tier was the reason you were there.
- Preview environment platforms in 2026: what is in the database when the preview comes upEvery platform on this list will give a pull request its own URL. The question that sorts them is what is in the database behind that URL: nothing, a restore of last night's backup, or the live data as of right now. Here is where each of eleven platforms lands, quoted from their own docs, and what a preview costs while the PR sits open.
- Northflank alternatives: a preview environment is not a database branchNorthflank gives every pull request its own stack, and the database in that stack starts empty unless you seed it or restore it from a backup you already had. Here is exactly how their forks work, what a copy-on-write branch does differently, what each one costs while a PR sits open, and the cases where Northflank is the right answer.
- Crunchy Bridge alternatives: what the Snowflake acquisition did and did not changeSnowflake bought Crunchy Data in June 2025. Bridge is still sold, still documented, and nothing has been announced about sunsetting it. Here is the dated record, what it actually implies, and the reasons to move that have nothing to do with the acquisition.