Migrating from Postgres to SQLite
This guide covers migrating an existing HappyView deployment from Postgres to SQLite. If you are staying on Postgres, no action is required.
Overview
HappyView now defaults to SQLite and writes all internal SQL in SQLite syntax. When running against Postgres, HappyView translates queries automatically. However, if you have Lua scripts that contain raw Postgres SQL, those scripts need to be updated to use SQLite syntax instead.
Step 1: Export your data
Back up your Postgres database before making any changes:
pg_dump -U happyview happyview > happyview_backup.sql
Step 2: Update environment variables
Change your .env to use SQLite:
# Before
DATABASE_URL=postgres://happyview:happyview@localhost/happyview
# After
DATABASE_URL=sqlite://data/happyview.db?mode=rwc
If you had DATABASE_BACKEND set, update it as well:
DATABASE_BACKEND=sqlite
Step 3: Migrate Lua scripts
If you have Lua scripts with raw SQL queries, they need to be converted from Postgres syntax to SQLite syntax. A codemod tool is provided to automate this.
Run the codemod tool
cargo run --bin migrate-lua-sql -- /path/to/lua/scripts
The tool scans all .lua files in the given directory and rewrites Postgres SQL patterns to SQLite equivalents.
What the codemod converts automatically
$1,$2, etc. parameter placeholders to?- JSON operators (
->,->>) and::jsonbcasts tojson_extract()calls ILIKEtoLIKE(SQLiteLIKEis case-insensitive for ASCII by default)NOW()todatetime('now')NOW() + INTERVAL '...'/NOW() - INTERVAL '...'todatetime('now', '...')TRUE/FALSEliterals to1/0
What it flags for manual review
The tool prints warnings for patterns it cannot convert automatically:
- JSONB
?(contains-key) operator — consider usingjson_each()with anEXISTSsubquery make_interval()— Postgres-specific, needs manual conversionSIMILAR TO— useLIKEorGLOBinsteadANY()/ALL()array operators — no direct SQLite equivalent- Type casts other than
::jsonb(e.g.,::text,::integer) — may need manual conversion toCAST(... AS ...)
Review the flagged lines and update them manually.
Step 4: Import data into SQLite
Start HappyView with the new DATABASE_URL. It will create the SQLite database and run migrations automatically. If you need to import existing records, use the backfill feature to re-index from the network:
- Start HappyView with the new SQLite
DATABASE_URL - Upload your lexicons via the dashboard or admin API
- Run a backfill for each collection (dashboard or
POST /admin/backfill)
For small datasets, this is the simplest approach since backfill fetches all records fresh from the network.
Step 5: Update Docker Compose (if applicable)
If you were running Postgres via Docker Compose, you can now comment out the postgres service since it is no longer needed. See the database setup guide for details.
Rollback
To switch back to Postgres, revert your DATABASE_URL to the Postgres connection string. Your Postgres database remains unchanged — HappyView does not modify it during the migration to SQLite.
Next steps
- SQLite → Postgres migration — migrate in the opposite direction
- Database setup — choose between SQLite and Postgres for new instances
- Backfill — re-index records from the network after switching backends
- Lua scripting — write SQL that works against either backend