Comparisons

This page compares pg_trickle to adjacent tools so you can decide whether it's the right fit. Each comparison is a short, honest summary — strengths, weaknesses, and "use this instead if…".

If you are evaluating pg_trickle from a specific tool you already run, jump to the relevant section. If you want a deeper academic comparison, see also DBSP Comparison, pg_ivm Comparison, and Prior Art.


At a glance

ToolLives in PostgreSQL?Incremental?External infra?Best for
pg_trickleSelf-maintaining materialized views inside one PostgreSQL
REFRESH MATERIALIZED VIEWPeriodic full recomputation, no automation
pg_ivm✅ (limited)Incremental views with a smaller SQL surface
Materialize✕ (own engine)Whole new databaseCross-source streaming SQL
Feldera✕ (own engine)Separate serviceDBSP-based incremental SQL for data pipelines
RisingWave✕ (own engine)Whole new databaseStreaming SQL with PostgreSQL wire compat
DuckDB + DuckLake✅ (via pg_trickle)Object storageAnalytical queries on a Parquet/Iceberg lake
Apache FlinkJVM cluster + state backendStateful event processing at scale
Debezium + sink(CDC only)Kafka + ConnectReplicating change events out of PostgreSQL
ksqlDBKafka clusterStreaming SQL on top of Kafka
Snowflake Dynamic TablesSnowflakeAuto-refreshing tables in Snowflake
Custom cron + materialized viewWhat teams build before they find pg_trickle

vs. PostgreSQL REFRESH MATERIALIZED VIEW

The question this answers: "I'm already using materialized views — what would I gain?"

REFRESH MATERIALIZED VIEWpg_trickle stream table
Refresh triggerManual (or your cron)Schedule, transition, or in-transaction (IMMEDIATE)
Refresh costAlways full recomputationIncremental (delta only) for most queries
Cross-table dependenciesManual coordinationDAG-aware topological refresh
ConcurrencyCONCURRENTLY requires unique indexAlways non-blocking; advisory locks coordinate
Read-your-writesNot possibleIMMEDIATE mode
Operator coverageAnything PostgreSQL supportsA large but explicit subset (see SQL Reference)

Use vanilla materialized views if: you only refresh occasionally, your data is small, and you do not have a chain of dependent views.

Switch to pg_trickle if: any of those things stop being true.


vs. pg_ivm

The question this answers: "There's another PostgreSQL extension in this space — how do they relate?"

pg_ivm is an open-source IVM extension that pioneered much of the relevant work in PostgreSQL land. The two projects have different scopes.

pg_ivmpg_trickle
MaturityFirst released 2022First released 2024
Refresh modelTrigger-driven, statement-by-statementTrigger or WAL CDC + scheduler + DAG
SQL coverageAggregates, simple joins, sub-queriesFull DBSP-style coverage incl. WITH RECURSIVE, window functions, FULL OUTER JOIN, LATERAL, GROUPING SETS, scalar subqueries
Cross-table chainsManualDAG with topological refresh and CALCULATED schedules
ModesAlways immediateAUTO / DIFFERENTIAL / FULL / IMMEDIATE
DistributedCitus integration
OperationsMinimal toolingHealth-check, fuse, parallel refresh, snapshots, dbt

There is a more thorough side-by-side at research/PG_IVM_COMPARISON.md.

If your queries are simple aggregates and you want the smallest possible install footprint, pg_ivm is a perfectly good choice. If you want broader SQL, multi-layer DAGs, or operational tooling, pg_trickle is closer to that shape.


vs. Materialize

Materialize is a cloud-native database built specifically for incremental view maintenance. It is the inspiration for much of this space.

Materializepg_trickle
DeploymentSeparate cloud database (or self-hosted server)Extension inside PostgreSQL
Source coveragePostgreSQL, Kafka, S3, MySQL, …PostgreSQL tables (incl. Citus, foreign tables)
LatencyStreaming, sub-secondSub-second with 1s schedule; in-transaction with IMMEDIATE
Joins / aggregates / recursionYes, very matureYes
PricingCommercial cloud productOpen-source, runs anywhere PostgreSQL runs
Operational footprintManaged service or significant self-hosted commitmentAdd-on to existing PostgreSQL

Use Materialize if: you want one engine to materialise across many heterogeneous sources, you want true streaming semantics, and you are happy operating a separate database.

Use pg_trickle if: your data lives in PostgreSQL and you want the materialisation to live there too.


vs. RisingWave

RisingWave is a PostgreSQL-wire-compatible streaming database in Rust. Like Materialize, it is its own engine that you deploy alongside (or instead of) PostgreSQL.

The same trade-off applies: RisingWave is a richer streaming engine; pg_trickle is the answer if you do not want to operate a second database.


Flink is a general stateful stream processor. It can do everything pg_trickle can and a lot more — including state-machine workflows, event-time semantics, and complex windowing.

The trade-off is operational. Flink wants a JVM cluster, a state backend (RocksDB / S3), checkpointing, savepoint management, a schema registry, and so on. For "I want my materialized views to update themselves", that is overkill.

Use Flink if: you have stateful event processing that goes beyond derived tables — state machines, complex CEP, multi-source joins at high throughput.

Use pg_trickle if: you want stream-table semantics and you are already running PostgreSQL.


vs. Debezium + sink (Kafka Connect, etc.)

Debezium captures changes from PostgreSQL and emits them onto Kafka (or another stream). It is only the change-capture half of the problem — you still need a downstream consumer that turns those changes into a derived table.

Debeziumpg_trickle
Captures changes from PostgreSQL✅ (built-in CDC)
Computes derived tables✕ (you write that)
Kafka required
Downstream sinksManyLogical replication via downstream publications

Use Debezium if: you need to fan changes out to many heterogeneous downstream systems (Elasticsearch, S3, Snowflake, a data lake).

Use pg_trickle if: you want the derived table to live in PostgreSQL itself. You can still expose stream-table changes via downstream publications — and even use Debezium to read those.


vs. ksqlDB

ksqlDB gives you streaming SQL on top of Kafka. Same trade-off as Materialize/RisingWave: another engine, another set of operational concerns.

If your data already lives in Kafka and you want SQL on it, ksqlDB is a fine choice. If your data lives in PostgreSQL, pg_trickle is closer to where it already is.


vs. Snowflake Dynamic Tables

Snowflake Dynamic Tables are auto-refreshing tables inside Snowflake. They occupy almost exactly the same conceptual slot as pg_trickle — but in a different database.

Use whichever matches the database you have.


vs. "cron + REFRESH MATERIALIZED VIEW"

This is what most teams build before they find a real IVM tool. It works, until:

  • Refreshes start to overlap.
  • A long refresh blocks readers.
  • The refresh becomes too expensive to run as often as you'd like.
  • A second view depends on the first and you start writing ordering logic.
  • A failure leaves stale data and nobody notices.

When that happens, pg_trickle's quick start is ~5 minutes of setup.


vs. Feldera

Feldera is an open-source incremental SQL engine built on DBSP — the same Z-set / differential dataflow theory that underlies pg_trickle's DVM engine. Both systems are implementations of the same mathematical model, but they occupy very different deployment shapes.

Felderapg_trickle
DeploymentSeparate service (Docker / cloud)Extension inside PostgreSQL
Data lives inFeldera's own storage / external connectorsPostgreSQL
Source coverageKafka, PostgreSQL CDC, S3, HTTP, and more via connectorsPostgreSQL tables (incl. Citus, foreign tables, DuckLake)
SQL surfaceSQL:2016 subset (aggregates, joins, window functions, UDFs)Very similar surface plus WITH RECURSIVE, LATERAL, GROUPING SETS
Theoretical basisDBSP Z-sets (same as pg_trickle)DBSP Z-sets
LatencySub-second streaming (push model)Sub-second with 1s schedule; in-transaction with IMMEDIATE
Consistency modelEpoch-based snapshot consistencyPostgreSQL MVCC + per-refresh transaction
Operational modelAPI-driven pipeline managementSQL DDL (CREATE STREAM TABLE, ALTER STREAM TABLE)
PricingOpen-source + managed cloud offeringOpen-source, runs anywhere PostgreSQL runs
EcosystemKafka-native; Rust/Python SDKPostgreSQL-native; dbt, CNPG, Grafana

Shared DNA: Both systems use Z-set multiset semantics, support nested deltas, and handle the same set of SQL operators (INNER JOIN, LEFT JOIN, aggregates, subqueries, etc.) in an incremental manner. Feldera's open-source codebase and pg_trickle have independently implemented the same core delta rules from the DBSP paper.

Use Feldera if: you want a dedicated streaming pipeline service with first-class Kafka integration, and you are comfortable managing a separate service. Feldera shines when your data arrives from multiple heterogeneous sources and you want a unified pipeline API.

Use pg_trickle if: your data already lives in PostgreSQL and you want the incremental computation to live there too — no extra service to deploy, no Kafka required.


vs. DuckDB / DuckLake

DuckDB is an in-process OLAP engine. DuckLake is a PostgreSQL-catalog-backed Delta Lake / Iceberg format that DuckDB can write and query.

These two projects occupy a complementary position to pg_trickle, not a competing one. The combination PostgreSQL + pg_trickle + DuckLake + DuckDB gives you a full modern data stack in a surprisingly small footprint:

LayerToolRole
OLTP storagePostgreSQLTransactional writes
Incremental aggregationpg_trickleKeeps derived tables fresh
Historical / analytical archiveDuckLake (on S3)Long-retention Parquet store
Ad-hoc OLAP queriesDuckDBFast analytical queries

Pg_trickle v0.66+ supports a DuckLake sink that writes stream-table results directly into DuckLake as Parquet snapshots, closing the full bidirectional loop.

DuckDB/DuckLake alonepg_trickle + DuckLake
Incremental maintenance✕ (DuckDB re-reads full snapshot)✅ (O(Δ) differential refresh)
Lives in PostgreSQL
Writes to object storage✅ (DuckLake native)✅ (via DuckLake sink, v0.66+)
Change capture from PostgreSQL✅ (trigger CDC or WAL CDC)
SQL coverage for IVMN/AFull DBSP coverage

Comprehensive IVM comparison matrix

This table covers the five most commonly evaluated IVM systems across eight axes. Ratings are approximate and based on publicly available information as of 2026.

SQL coverage

Featurepg_ivmMaterializeFelderaDuckDB (MV)pg_trickle
INNER JOIN
LEFT / RIGHT JOIN✅ (basic)
FULL OUTER JOIN
Aggregates (COUNT, SUM, AVG…)✅ (39 aggregate functions)
DISTINCT
HAVING
Scalar subqueries
EXISTS / NOT EXISTS
NOT IN / anti-join
WITH RECURSIVE
Window functions
LATERAL
GROUPING SETS / CUBE / ROLLUP
JSON aggregates

Consistency model

pg_ivmMaterializeFelderaDuckDB (MV)pg_trickle
Isolation levelPostgreSQL MVCCLinearizable (own store)Epoch-based snapshotPer-query snapshotPostgreSQL MVCC
Results always fresh?Yes (immediate)Yes (streaming)Yes (epoch-based)No (manual refresh)Configurable (IMMEDIATE / scheduled)
Read-your-writes✅ (IMMEDIATE mode)
Atomic multi-view refresh✅ (pipeline epoch)✅ (diamond consistency groups)

Change data capture (CDC)

pg_ivmMaterializeFelderaDuckDB (MV)pg_trickle
Capture mechanismStatement-level triggersLogical replication slotExternal connectors (Kafka, HTTP, …)Full re-scanRow-level AFTER triggers OR WAL CDC
Multi-source✅ (Citus, foreign tables, DuckLake)
Kafka source✕ (use Debezium + pg_trickle)
Cost of captureMedium (trigger overhead)Medium (replication lag)Low (connector-based)High (full scan)Low to medium (trigger or WAL)

Performance profile

pg_ivmMaterializeFelderaDuckDB (MV)pg_trickle
Refresh cost per changeO(Δ)O(Δ)O(Δ)O(full table)O(Δ)
Minimum refresh latencyIn-transactionSub-secondSub-secondManual triggerIn-transaction (IMMEDIATE) or ≥ 1 s (scheduled)
Throughput at scaleMedium (single PG)High (distributed)High (parallel pipeline)High (columnar OLAP)Medium-high (parallel refresh pool)
TPC-H 22/22 differentially✅ (v0.23.0+)

Operational model

pg_ivmMaterializeFelderaDuckDB (MV)pg_trickle
Deployment unitPostgreSQL extensionSeparate database serviceSeparate service (Docker / cloud)In-process libraryPostgreSQL extension
Admin surfaceSQL DDLPlatform API + SQLPipeline YAML + SQLSQLSQL (CREATE STREAM TABLE)
MonitoringNone built-inMaterialize consoleMetrics endpointNone built-in30+ SQL functions, Prometheus, Grafana
Backup / restorePostgreSQL pg_dumpManaged (cloud)ExternalDuckDB exportPostgreSQL pg_dump (v0.8.0+)
High availabilityPostgreSQL HABuilt-in (cloud)ExternalExternalCNPG / Patroni + pg_trickle HA guide
Multi-tenantRLS on base tablesIsolated environmentsIsolated pipelinesFile-level isolationRLS on stream tables (v0.5.0+)
dbt integration✅ (dbt-materialize)✅ (dbt-duckdb)✅ (dbt-pgtrickle, v0.15.0+)

Disclaimer: Feature support changes rapidly in all these projects. Verify current capabilities in each project's own documentation before making a production architecture decision.


See also: Use Cases · Migrating from materialized views · Migrating from pg_ivm · Research and prior art