Skip to main content

Overview

PropertyValue
Engine IDduckdb
Wire Protocolpgwire (exposed by Mori)
ClassifierRegex-based
ShadowLocal file copy (full data, not schema-only)
Docker RequiredNo
DuckDB is an embedded analytical database. Same architecture as SQLite — Mori opens both prod and shadow DuckDB files directly and exposes them through a pgwire listener. Applications connect with any PostgreSQL driver.
The shadow is a full copy of the production database file, including all data. For large analytical databases, be aware of disk space implications.
Connection Parameters:
FieldDescription
file_pathPath to the DuckDB file
Supported connection string formats:
mori init --from "/path/to/analytics.duckdb"
mori init --from "duckdb:///path/to/analytics.duckdb"

Differences from PostgreSQL

  • Full file copy shadow — Complete copy of the production database including all data. The prod file is opened with access_mode=READ_ONLY, providing database-level write protection.
  • Regex-based classification — Handles DuckDB-specific constructs: INSERT OR REPLACE, INSERT OR IGNORE, CREATE OR REPLACE TABLE, DESCRIBE, PRAGMA, INSTALL, LOAD, QUALIFY.
  • rowid for PK-less tables — Uses DuckDB’s implicit rowid column for deduplication.
  • JOIN via materialization — Dirty tables are materialized into temp tables on shadow, the JOIN SQL is rewritten to reference them, and DuckDB handles the JOIN natively.
  • Aggregate via materialization — All aggregates (COUNT, SUM, AVG, MIN, MAX, GROUP BY, list(), array_agg, etc.) use materialization — base data is merged into a temp table, then DuckDB handles aggregation natively. This plays to DuckDB’s strengths as an analytical engine.
  • WHERE clause evaluator — Regex-based with DuckDB fallback: constructs SELECT 1 WHERE <condition> on shadow for complex expressions.
  • DuckDB type mapping — Maps DuckDB types to PostgreSQL OIDs for pgwire compatibility. Nested types (LIST, STRUCT, MAP, UNION) map to JSON OID. Unsigned integers map to the next larger signed PostgreSQL type.
  • INSERT OR REPLACE for hydration — DuckDB-specific upsert semantics for hydrating prod rows into shadow.
  • No Docker required — Shadow is a local file copy.
  • No cursor support — Cursors are not classified or handled.
  • No LISTEN/UNLISTEN — Not applicable to DuckDB.

Known Limitations

  • No cursor operations.
  • DuckDB-specific SQL syntax not parseable by pg_query_go — but DuckDB uses its own regex classifier, so this is handled.
  • LIST() / ARRAY_AGG() results serialize as JSON through pgwire (nested types).
  • Unsupported operations: COPY/EXPORT/IMPORT, EXPLAIN ANALYZE.