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.