Database support

Lean CMS is built for SQLite in production — but the gem’s schema is pure Rails migration DSL, so it works on any database adapter ActiveRecord supports. SQLite is the happy path; Postgres and MySQL are first-class compatibility targets.

Quick read

Adapter Status When to pick it
SQLite Happy path New marketing sites, single-server deployments, Kamal one-droplet setups, the lean_cms:sync:* workflow
PostgreSQL Compatible, verified Existing Rails app already on PG, multi-server deployments, JSONB queries, full-text search you want to build on top of
MySQL Compatible, untested at write time Existing Rails app already on MySQL — schema works, no gem-shipped tooling assumes SQLite-only formats

Verified end-to-end on Postgres as of v0.2.12 (PR #29): fresh Rails 8 --database=postgresql host, install generator, all gem-shipped migrations (lean_cms_*, PaperTrail versions, Action Text, Active Storage, Noticed), lean_cms:load_structure, and the rich_text association — all clean with zero gem changes.

Installing on Postgres or MySQL

Same as the getting-started install. Choose your database when you rails new:

rails new my-site --database=postgresql   # or --database=mysql
cd my-site
bin/rails db:create
bin/rails generate authentication         # or your auth gem of choice
bundle add lean_cms
bin/rails generate lean_cms:install

The gem’s migrations run cleanly on all three adapters. Action Text + Active Storage tables come with the gem (you don’t need to run bin/rails action_text:install / active_storage:install separately).

Feature compatibility

Gem feature SQLite PostgreSQL MySQL
Page content + sections
Rich text editing (Action Text + Trix)
Image upload (Active Storage)
Cards + bullets components
Blog posts (PaperTrail history)
Settings (LeanCms::Setting)
Notifications (Noticed)
lean_cms:sync:{lock,unlock,status} rake tasks
lean_cms:sync:{pull,push,stage,start,finish} rake tasks ❌ — use pg_dump / mysqldump ❌ — use mysqldump

The sync file-copy tasks cp the production SQLite file to/from your laptop. They’re guarded — on Postgres or MySQL they exit cleanly with a message pointing at the native dump/restore tooling. The lock/unlock/status tasks only toggle a LeanCms::Setting and work on every adapter.

When to switch

docs/deployment/sqlite/#when-to-consider-postgres has the full list. The short version:

  • Multiple app servers behind a load balancer → Postgres
  • Several editors writing at once all day → Postgres
  • You’re already running PG/MySQL for the rest of the app → use that

For a single-server marketing site with a handful of editors, stay on SQLite. The Kamal deploy is trivial, the lean_cms:sync:* workflow saves real time, and 37signals runs HEY on SQLite.

Production data sync

The SQLite content sync workflow is SQLite-specific by design. On Postgres or MySQL, use your database’s native tooling:

# Postgres
pg_dump $PRODUCTION_URL > prod.sql
psql $DEVELOPMENT_URL < prod.sql

# MySQL
mysqldump -h prod_host my_db > prod.sql
mysql -h dev_host my_db_development < prod.sql

A LeanCms::Setting.lock_content! call before the dump and unlock_content! after still works the same way to block editor writes during the sync window — those are adapter-agnostic.