Move a whole Postgres database to the cloud and back, and count every row
Move Database copies a whole Postgres database between a connection on your computer and SnoutData Cloud, in either direction. It checks both ends before anything runs, shows each table as it copies, and finishes by counting every table's rows on both sides.
There are two trips people actually make. A hosted project comes down to a laptop, to debug against real data or to work somewhere without a network. And the database somebody has been building locally goes up into a hosted project, very often one that does not exist yet, so the move can create it on the way.
Either way it is one screen: pick the source, pick the target, choose schema and data, schema only or data only, and choose what happens to the source afterwards.
pg_restore said it was fine
Before building any of it, we moved real hosted projects by hand with the standard Postgres tools and wrote down every line they printed. The first restore finished like this:
errors ignored on restore: 16
Among sixteen errors that looked like housekeeping, the orders table and all 300,000 of its rows did not arrive. The target had no vector extension, so the type did not exist, so the table could not be created, so every statement after it on that table failed too.
Measured: a 48 MB hosted project restored into a stock Postgres 17, 2026-09-13.
A missing extension is not one object that fails. It silently takes every table with a column of its type. So the check now names each of those tables with its row count before you start, and that is the finding worth reading carefully.
The second surprise was replacing a target. The tools' own --clean drops only what the archive contains, so a table that existed only on the target was still there afterwards. And dropping the public schema on a hosted project takes objects its data API depends on with it. So a replace empties public object by object, drops other schemas whole, and lists every drop by name before you confirm.
Checked before, verified after
The check reads both databases: versions, extensions, whether the target already holds tables, whether a new database's name is taken or the connection is allowed to create one, and whether the target is marked production, which means typing its name. Each finding says what it found in a sentence and offers the ways to deal with it. Nothing runs until every finding that needs a decision has one, and both databases are checked once more just before the move starts.
Replacing a hosted project that holds data saves a copy of it first, as a cloud export. If that copy fails, the move does not start, and when it finishes the report links to it.
While it runs you see each table with its rows and bytes, the rate and the time left, read from Postgres's own copy progress on the target. A paused project is woken first, and the screen says so rather than sitting still. At the end, the report compares the exact row count of every table on both sides, checks the sequences, and lists anything that did not restore with the statement that failed.
The source afterwards
By default the source is left exactly as it was, so a move is a copy. A SnoutData Cloud source can be paused instead, or deleted. Delete is offered only for a move that copies all of it, happens only if every object restored and every row count matched, and asks you to type the project's name. A partial or stopped run never touches the source, and a deleted project can still be recovered for your plan's grace period.
Numbers
One stream of 5.3 GB and 14 million rows, from a Windows machine on home broadband into a hosted project in us-west-2: 282 seconds, about 18.8 MB/s, zero errors, and the rate held flat from under a gigabyte to five.
Through the app, with a 200,000-row database: a paused project woken, exported, emptied and refilled in 17.6 seconds, and a project created by the move, ready and filled in 29.9 seconds.
Where your password goes
A move runs Postgres 17's own pg_dump and pg_restore, downloaded once, pinned and hash-checked, never whichever version happens to be on your PATH. The app hands them credentials in their environment, never on a command line.
Your data goes directly between the app and the database. For a hosted project that means through the front door that serves that database, and through no other SnoutData service.
What it is not
A move is a copy taken at one moment, not a live migration. Anything written to the source after it starts is not in the target, and shows up in the report as a row count that does not match, so move a busy database when it is quiet. Owners and grants do not move, because roles belong to a server: everything is created as the user the target connection signs in with. It is Postgres only for now, and a connection that goes through an SSH tunnel cannot be moved yet.
Try it
In the desktop app, click the two-arrow icon in the side bar, choose File, Move Database, or run Move Database from the command palette. The first time, it offers to download the Postgres tools, a few megabytes. Download SnoutData or read the Move a database docs.