Skip to content

Storage Backends

pH7x Systems edited this page Jul 21, 2026 · 4 revisions

Storage Backends

Storage is a strict contract (cms_core.storage.StorageBackend) with versioned, shared ANSI migrations. The database is never the portable source of truth — JSON/Markdown export is.

Supported engines

Engine URL Notes
SQLite (default) sqlite:///content.sqlite3 Development and small sites; WAL mode + busy timeout
PostgreSQL postgresql://user:pass@host:5432/db Production; pip install "sardine-cms-core[postgres]" (psycopg 3)
MySQL / MariaDB mysql://user:pass@host:3306/db (alias mariadb://) pip install "sardine-cms-core[mysql]" (PyMySQL, pure Python)
SQL Server mssql://user:pass@host:1433/db (alias sqlserver://) pip install "sardine-cms-core[mssql]" (pymssql, no ODBC setup)

Every engine promised by the factory (ADR-0004) is implemented. The shared ANSI migration history applies everywhere; MySQL and SQL Server adapt it mechanically at migrate time (bounded VARCHAR key columns, NVARCHAR(MAX) on T-SQL, quoted reserved words) — the same history, four engines, one conformance suite.

Usage

from cms_core import create_storage

with create_storage("sqlite:///content.sqlite3") as storage:
    storage.migrate()                 # apply pending schema migrations
    print(storage.schema_version())   # current version
    articles = storage.load_all_articles()

The factory (create_storage(url)) resolves the engine from the URL scheme — every caller (CLI, admin, your code) works unchanged across engines.

Contract surface

Content search: search_content(needle, limit) — a portable base default (walks loaded content) that the bundled engines override with LIKE queries; third-party backends inherit correctness and may override for speed (ADR-0038).

Articles, pages and media assets: save_* / load_* / delete_* / list_*_ids / load_all_*. Admin accounts and sessions: save_user / load_user / delete_user / list_usernames, save_session / load_session / delete_session / delete_expired_sessions. Accounts live in the database via the shared migrations but are never exported.

Migrations

Numbered, shared across engines, tracked per engine (SQLite user_version, PostgreSQL a version table). storage.migrate() is idempotent; the admin's /healthz reports the migrated schema version.

Conformance suite

Every engine runs the same test suite. SQLite always runs; PostgreSQL, MySQL and SQL Server run when SARDINE_POSTGRES_URL / SARDINE_MYSQL_URL / SARDINE_MSSQL_URL are set (CI uses service containers; locally any instance works — the suite wipes its tables between tests). Never silently faked: unset URL means skipped, visibly.

Clone this wiki locally