Move from SQLite to Postgres
What you'll build
The same site on Postgres instead of SQLite: before launch (easy), or with content you want to keep. Uses: databases, migrations, backups.
SQLite is a fine choice for one server with a disk. Move to Postgres when you deploy to serverless, run several servers, or your host offers managed Postgres with backups.
Before launch: switch and start fresh
If the content so far is test content, switch the adapter and recreate it:
npm install @easy-cms/db-postgres @electric-sql/pglitepnpm add @easy-cms/db-postgres @electric-sql/pgliteyarn add @easy-cms/db-postgres @electric-sql/pglitebun add @easy-cms/db-postgres @electric-sql/pgliteimport { postgres } from '@easy-cms/db-postgres'
db: process.env.DATABASE_URL
? postgres({ url: process.env.DATABASE_URL })
: postgres({ pglite: '.pglite' }), // local Postgres in a folder, no server neededMigrations are written in one database's SQL, so replace the SQLite ones:
rm -r easy-cms/migrations
npx easy-cms migrate:create initrm -r easy-cms/migrations
pnpm exec easy-cms migrate:create initrm -r easy-cms/migrations
yarn easy-cms migrate:create initrm -r easy-cms/migrations
bunx easy-cms migrate:create initCommit the new folder, run npx easy-cms migrate where you deploy, and create the first admin again (npx easy-cms create-admin).
With content to keep
easy-cms copy moves everything: documents, versions, users (so logins keep working), globals, scheduled jobs. Ids stay the same, so relationships still point to the right documents.
Back up first:
npx easy-cms backup backups/before-postgres.db.Keep a config for the old database. Create
easy-cms.old.config.tsnext to the main config; it reuses everything and changes onlydb:tsimport { sqlite } from '@easy-cms/db-sqlite' import config from './easy-cms.config' export default { ...config, db: sqlite({ url: 'file:./cms.db' }) }Point the main config at Postgres, as in the section above, and create the Postgres migrations (
rm -r easy-cms/migrations && npx easy-cms migrate:create init).Prepare the new database. Locally (PGlite, or
DATABASE_URLset) the next step creates the tables itself. For a production database runNODE_ENV=production npx easy-cms migratewith itsDATABASE_URLfirst.Copy, while nobody is editing:
bashnpx easy-cms copy --from easy-cms.old.config.ts # Copying from sqlite (easy-cms.old.config.ts) to postgres… # ecms_users: 3 # ecms_posts: 42 # … # Copied 318 row(s) from 17 table(s).bashpnpm exec easy-cms copy --from easy-cms.old.config.ts # Copying from sqlite (easy-cms.old.config.ts) to postgres… # ecms_users: 3 # ecms_posts: 42 # … # Copied 318 row(s) from 17 table(s).bashyarn easy-cms copy --from easy-cms.old.config.ts # Copying from sqlite (easy-cms.old.config.ts) to postgres… # ecms_users: 3 # ecms_posts: 42 # … # Copied 318 row(s) from 17 table(s).bashbunx easy-cms copy --from easy-cms.old.config.ts # Copying from sqlite (easy-cms.old.config.ts) to postgres… # ecms_users: 3 # ecms_posts: 42 # … # Copied 318 row(s) from 17 table(s).The target must be empty, so running it twice by accident changes nothing.
Check the site: open the admin, a few documents with relationships and images, the history of a post, and log in.
Uploads don't move: they stay in uploads/ or your bucket, and documents keep pointing to them. When the site runs well on Postgres, delete easy-cms.old.config.ts (keep the backup a while).
The same command works the other way, from Postgres to SQLite.