From 7a77659e52e80e5e823962a8e1051f66cdafaa7c Mon Sep 17 00:00:00 2001 From: Tom Boutell Date: Tue, 2 Jun 2026 13:29:14 -0400 Subject: [PATCH] Revert "Revert "PRO-9358 document APOS_DEFAULT_ADAPTER"" --- docs/guide/using-sqlite-and-postgres.md | 154 ++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 docs/guide/using-sqlite-and-postgres.md diff --git a/docs/guide/using-sqlite-and-postgres.md b/docs/guide/using-sqlite-and-postgres.md new file mode 100644 index 00000000..72f57949 --- /dev/null +++ b/docs/guide/using-sqlite-and-postgres.md @@ -0,0 +1,154 @@ +# Using SQLite or PostgreSQL Instead of MongoDB + +ApostropheCMS has historically required MongoDB, and MongoDB remains the default. In addition to MongoDB, projects can now run on **SQLite** or **PostgreSQL** through the `@apostrophecms/db-connect` adapter layer. The adapter is transparent to application code: the same models, queries, cursors and aggregations work identically across all three backends. + +This guide is intended for developers who already know *why* they want to use SQLite or PostgreSQL — for example, to avoid running a database server entirely in local development by using SQLite, or to consolidate on an existing PostgreSQL infrastructure. It does not try to convince you to switch. If you are happy with MongoDB, there is no reason to change. + +::: info +A future version of the Apostrophe CLI will prompt for your preferred database when creating a new project. Until that lands, the simplest way to try a non-MongoDB backend is to clone the public demo and point it at a different database by setting one environment variable. +::: + +::: warning Pre-merge note (remove before publication) +All links to the `@apostrophecms/db-connect` module on this page currently point to the `postgres` branch of `apostrophecms/apostrophe` for QA convenience. Before this page is published, every `…/blob/postgres/packages/db-connect/…` and `…/tree/postgres/packages/db-connect/…` URL on this page must be re-pointed to `main`. +::: + +## Prerequisites + +- Node.js and a working Apostrophe development environment (see [Development Setup](development-setup.md)). +- For PostgreSQL: a running PostgreSQL 14+ server you can connect to (local, Docker, or managed). +- For SQLite: no server. A file on disk is the entire database. + +No changes to your project's `package.json` or module code are required. Apostrophe loads the right adapter based on the protocol in your connection URI. + +## Starting from the public demo + +The quickest way to try this out is the [public demo project](https://github.com/apostrophecms/public-demo): + +```bash +git clone https://github.com/apostrophecms/public-demo.git +cd public-demo +npm install +``` + +Apostrophe reads the database connection string from the `APOS_DB_URI` environment variable. By setting it to a non-`mongodb://` URI, you switch backends without editing a single line of project code. + +## Using SQLite + +SQLite is the easiest option for local development and small sites: the database is a single file, there is no server to run, and backups are a file copy. + +Point `APOS_DB_URI` at a file path using the `sqlite://` protocol: + +```bash +export APOS_DB_URI=sqlite:///absolute/path/to/apos-demo.db +npm run dev +``` + +The triple slash is intentional — `sqlite://` is the protocol, and the path that follows is absolute. Use a relative path with a double slash if you prefer: + +```bash +export APOS_DB_URI=sqlite://./data/apos-demo.db +``` + +The file is created on first run, along with all tables and indexes. To start over, stop the process and delete the file. + +::: warning +In-memory SQLite (`sqlite://:memory:`) is not supported. Apostrophe opens multiple connections to the database, and an in-memory database is only visible to the connection that created it. Use a real file on disk — even a file in `/tmp` works fine for throwaway experiments. +::: + +## Using PostgreSQL + +PostgreSQL is a good choice when you want to consolidate on infrastructure that already runs PostgreSQL, or to use the operational tooling (backups, monitoring, replication) your team is already familiar with. + +Create an empty database and point `APOS_DB_URI` at it using the `postgres://` protocol: + +```bash +# Create the database (once) +createdb apos_demo + +# Run Apostrophe against it +export APOS_DB_URI=postgres://user:password@localhost:5432/apos_demo +npm run dev +``` + +On first run, Apostrophe creates the tables and indexes it needs inside that database. It does not touch other databases or schemas on the same server. + +If you prefer not to embed credentials in the URI, PostgreSQL's standard environment variables (`PGUSER`, `PGPASSWORD`, `PGHOST`, `PGPORT`) are honored: + +```bash +export PGUSER=apos +export PGPASSWORD=... +export APOS_DB_URI=postgres://localhost:5432/apos_demo +``` + +## Changing your default adapter + +By default, if you do not set `APOS_DB_URI` or `APOS_MONGODB_URI`, apostrophecms defaults to `mongodb://localhost:27017/your-shortName-here`. + +For local development, if you always use `sqlite` or `postgres`, you can optionally set the `APOS_DEFAULT_ADAPTER` environment variable to `sqlite` or `postgres` to get the same effect with your preferred database. + +If you set `APOS_DEFAULT_ADAPTER` to `sqlite`, then a `shortName` setting of `my-project` will point to the `sqlite://data/my-project.sqlite`, which refers to the `data/my-project.sqlite` file in your project. Make sure you add the file to `.gitignore` and be aware that if your project folder is removed, the database is gone too. + +If you set `APOS_DEFAULT_ADAPTER` to `postgres`, then a `shortName` setting of `my-project` will point to `postgres://localhost:5432/my-project`. + +If you choose this approach it is best to be consistent about it, e.g. set it in your `.bashrc` or `.zshrc` file. + +For multisite projects, this technique is not currently supported. Use `DB_URI` as described above. + +## Switching a project between backends + +Because the three URI formats are fully interchangeable, you can experiment with different backends on the same codebase by changing `APOS_DB_URI` alone. Each URI targets an independent database — there is no automatic migration between them. + +To migrate content between backends, use the `apos-db-dump` and `apos-db-restore` tools shipped with `@apostrophecms/db-connect`. They produce and consume a portable JSONL format that works across all three adapters. + +Because `@apostrophecms/db-connect` is already a transitive dependency of every Apostrophe project, the simplest way to run these tools is from inside your project directory with `npx` — no global install required: + +```bash +cd /path/to/your/apostrophe/project +npx apos-db-dump mongodb://localhost:27017/mydb --output=backup.jsonl +npx apos-db-restore postgres://localhost:5432/mydb --input=backup.jsonl +``` + +If you prefer them on your `PATH` for use across many projects, install globally instead: + +```bash +npm install -g @apostrophecms/db-connect +apos-db-dump mongodb://localhost:27017/mydb --output=backup.jsonl +``` + +See the [db-connect dump/restore documentation](https://github.com/apostrophecms/apostrophe/blob/postgres/packages/db-connect/docs/dump-restore.md) for the full set of options, including piping dump output straight into restore for cross-backend migration. + +## Multi-tenant deployments with the multisite module + +If you are using the [multisite module](https://apostrophecms.com/extensions/multisite-2) to host many Apostrophe sites from a single codebase, MongoDB, SQLite, and PostgreSQL are all supported. Two things differ from a single-site project: + +- Multisite reads its connection URI from the `DB_URI` environment variable (or the `dbUri` option), **not** `APOS_DB_URI`. +- Database, file, and schema names are derived from multisite's `shortNamePrefix` option (default `multisite-`). Each hosted site uses ``, and the dashboard uses `dashboard`. Because the dashboard is the one tenant guaranteed to exist, the convention is to point `DB_URI` at it: + +```bash +# MongoDB (default) +export DB_URI=mongodb://localhost:27017/multisite-dashboard + +# SQLite — the file's basename must equal dashboard +export DB_URI=sqlite:///var/lib/apostrophe/multisite-dashboard.db + +# PostgreSQL — use multipostgres://, not postgres://, see below +export DB_URI=multipostgres://user:password@localhost:5432/multisite-dashboard +``` + +If you change `shortNamePrefix` from the default, change every URI to match (e.g. `myapp-` → `myapp-dashboard`, `myapp-dashboard.db`). + +### Why `multipostgres://` and not `postgres://`? + +`multipostgres://` maps each site to its own **schema** inside a single shared PostgreSQL database, rather than provisioning a separate database per site. This matters because most managed PostgreSQL services (RDS, Cloud SQL, Neon, Supabase) bill, provision, and limit you per database, so a database-per-tenant model is rarely practical. + +A `multipostgres://` URI must include both a database name and a schema name, separated by the **last hyphen** in the path. In `multipostgres://.../multisite-dashboard`, `multisite` is the real PostgreSQL database name and `dashboard` is the schema for the dashboard site. The portion before the last hyphen must equal `shortNamePrefix` with the trailing hyphen removed; multisite substitutes each tenant's short name for `dashboard` when accessing per-site schemas at runtime. + +Plain `postgres://` is supported for single-tenant Apostrophe projects but is **not** appropriate for multisite. + +Refer to the [multisite extension page](https://apostrophecms.com/extensions/multisite-2) for installation and tenant-management documentation. + +## Compatibility notes + +All three adapters are provided by the [`@apostrophecms/db-connect`](https://github.com/apostrophecms/apostrophe/tree/postgres/packages/db-connect) module. `db-connect` implements a large subset of the MongoDB API — enough to support ApostropheCMS core and the extensions and patterns it relies on — but it does **not** attempt to cover 100% of the MongoDB API surface. Application code that sticks to the queries, cursors, aggregations, and index definitions Apostrophe itself uses will work across all three backends; code that reaches for less-common MongoDB features (obscure aggregation stages, server-side JavaScript, change streams, geospatial operators, and so on) may not. + +If you are writing modules intended to run across MongoDB, PostgreSQL, and SQLite, treat the db-connect API as authoritative rather than the full MongoDB driver API. See the [`db-connect` README](https://github.com/apostrophecms/apostrophe/blob/postgres/packages/db-connect/README.md) for the complete list of supported query operators, cursor methods, aggregation stages, and connection-URL formats, and the [db-connect docs folder](https://github.com/apostrophecms/apostrophe/tree/postgres/packages/db-connect/docs) for deeper material on the dump/restore format and adapter internals.