Context layers and real-time data products

Modern applications and AI systems depend on live context. They operate on business objects such as customers, orders, and accounts. These customers, orders and accounts are themselves assembled from operational tables joined together, rules applied, and values aggregated across systems. These business objects are derived state: when an input changes, the object must change with it.

Maintaining that state requires more than a database optimized for storing rows or scanning history. It requires a system that continuously assembles and maintains the current shape of the business as data changes, a live context layer.

A context layer maintains real-time data products, which are governed, derived datasets built from multiple sources, kept current as those sources change, and served directly to systems that act on them. Applications display them. APIs expose them. Automation workflows and AI agents make decisions from them.

A live context layer requires three properties. The data must be fresh and reflect what is true now. It must be correct, preserving updates, deletes, and transactional boundaries so results never reflect partial state. It must also be composable, allowing derived views to build on one another without introducing timing gaps or stale intermediate layers.

These requirements reinforce each other. Fresh but incorrect data accelerates mistakes. Correct but stale data misleads downstream systems. Composable but inconsistent data spreads errors.

AI agents make this constraint unavoidable. An agent that updates an order, checks inventory, and recalculates fulfillment performs dependent reads and writes in sequence. Each step assumes the last has taken effect. High concurrency and multi-step workflows leave little tolerance for delay or inconsistency.

This paper compares two systems through that lens: Materialize and ClickHouse. Both integrate with operational databases and support modern data-driven applications. Their designs, however, reflect different views of what the data layer should provide to the business.

These architectural priorities lead to different strengths. One approach centers on keeping operational state coherent and ready for action. The other centers on delivering high-performance analysis across accumulated data.

For teams investing in customer-facing features, automation, and AI-driven workflows, this distinction shapes what the data platform can enable. The choice determines whether the system primarily serves as a foundation for ongoing business operations or as a high-performance engine for large-scale analysis.

  • Materialize is built to continuously maintain the current shape of the business as data changes. It keeps customer records, orders, accounts, and other core entities aligned across systems so that applications, automation, and AI workflows operate on a consistent and up-to-date representation of the organization.
  • ClickHouse is built to execute fast queries over large volumes of stored data. It is optimized for summarizing activity, exploring trends, and analyzing historical information at scale.

Operational Systems + Reaction Time: Data freshness, correctness, and composability

Operational systems don't just store data, they act on data. Operational systems exist to respond to change, and they depend on freshness, correctness, and composability working together to minimize reaction time, which is the delay between a real world event and the system's response to it.

Freshness
Correctness
Composability
Reaction time begins with visibility. An application rendering account details, an API returning order status, or an agent applying a policy assumes that the context it's given reflects current state. Data that lags behind events extends reaction time because the organization is now acting on outdated information.
Reaction time also depends on confidence. Customers update profiles, orders change status, balances adjust, and changes committed together must become visible together. If derived results reflect partial or conflicting updates, downstream systems hesitate or require compensating logic. Confidence declines, and reaction slows.
Business entities span systems. A customer's eligibility may depend on order history, account standing, and profile data maintained in three separate locations. If these derived entities cannot be composed reliably, every new workflow introduces an additional coordination and synchronization burden. Each added layer increases latency between event and decision.

Minimizing reaction time requires simultaneous freshness, correctness, and composability. Speed without confidence does not shorten reaction time. Confidence without freshness does not shorten reaction time. Composability without either introduces coordination delays that offset gains.

Architecture dictates data change priorities

When data changes, systems can respond in two fundamentally different ways:

  • Change as primary. Mutations are ingested as they occur. Derived state is maintained incrementally. Consistency is preserved as a system-wide property.
  • Stored data as primary. Data is appended or written in batches. Queries reconcile versions at read time. Updates and deletes are handled through background processes and deduplication.

Each approach reflects a different workload priority.

Materialize is designed as a live context layer for operational workloads.

It connects directly to systems such as PostgreSQL, MySQL, SQL Server, and Kafka through change data capture or native connectors. Ingestion, computation, storage, and serving operate on a shared logical timeline. Derived data products are defined in standard SQL and maintained incrementally as source data changes.

ClickHouse is designed as a high-performance columnar database optimized for scanning and aggregating large datasets.

Its architecture emphasizes compression, vectorized execution, and efficient storage for substantial volumes of data. It excels at analyzing historical activity and summarizing trends across accumulated datasets.

Freshness in practice

The ability to act on current rather than prior state depends on how quickly changes move from source systems into the derived views that applications and agents actually read — and on how those results then reach the systems that consume them.

How Materialize handles data freshness

In Materialize, changes are processed as they arrive.

  • When a row changes in a source PostgreSQL database, the change is ingested through a direct CDC connection. All affected views update incrementally, including views built on other views. Results become available through the same continuous pipeline.
  • Because derived state is maintained ahead of time, query latency remains stable even as underlying data grows. Applications and services read from maintained state rather than recomputing it on demand.

How ClickHouse handles data freshness

ClickHouse ingests Postgres changes through ClickPipes on a configurable interval. The default is 60 seconds, and ClickHouse recommends keeping the interval above roughly 10 seconds. ClickPipes is a ClickHouse Cloud service; self-managed deployments use PeerDB, Debezium, or the MaterializedPostgreSQL engine, each with its own lag characteristics.

  • This ingestion interval introduces a latency floor between source systems and derived results. Even at lower intervals, data in ClickHouse reflects a prior state of the source.
  • For operational systems that act immediately on what they read, this delay shapes system behavior. As workflows chain reads and writes, timing gaps accumulate, propagating and growing through each downstream dependency.

Push-Based Architectures and Operational Responsiveness

The distinction between Materialize and ClickHouse becomes especially clear when considering how each system handles push-based architectures — systems designed to propagate changes outward as they occur, rather than waiting for downstream consumers to poll or query for updates.

What is a push-based architecture?

In a push-based architecture, the data layer takes responsibility for notifying or updating downstream systems the moment state changes. Rather than applications repeatedly asking "what changed?", the system pushes the answer to them.

This model is well-suited to operational workloads where:

  • Customer-facing applications need to reflect current state without polling
  • Automation workflows must trigger on specific conditions the instant they become true
  • AI agents need to observe changes in business entities as they happen

Materialize and push-based delivery

Materialize is built around a push-based model at its core. Its SUBSCRIBE command allows any downstream system — an application, an API layer, or an AI agent — to receive a continuous stream of changes as derived views update. For services that consume an event stream rather than hold a connection, a Kafka sink provides the same push semantics, carrying inserts, updates, and deletes as the view changes.

  • When a source row changes, all affected materialized views update incrementally
  • Connected subscribers receive the delta immediately, without issuing a new query
  • This eliminates the need for polling loops, reduces infrastructure complexity, and ensures consumers always act on current state

This architecture is particularly powerful for multi-step AI workflows, where each agent action depends on the result of the previous one being fully reflected in shared state.

ClickHouse and push-based patterns

ClickHouse has no changefeed that a connected client can subscribe to. Its query model is pull-based: consumers issue queries and receive results as of that point in time. It can push rows outward into Kafka, by pointing a materialized view at a Kafka table engine, but that path inherits the limits of incremental materialized views — it fires on inserts to the left-most table in its query, a constraint examined under Composability below, and does not carry updates or deletes for a composed entity.

For anything beyond appended rows, teams building push-like behavior on top of ClickHouse typically do so through external orchestration — scheduled jobs, change detection layers, or message queues that poll ClickHouse and propagate results. This adds coordination overhead and reintroduces the freshness gaps that push architectures are designed to eliminate.

For workloads requiring real-time propagation of operational state changes, this distinction matters: push behavior must be layered on top of ClickHouse, whereas it is a native capability of Materialize.

Correctness in practice

Holding confidence that derived state reflects complete, consistent updates is essential to reducing reaction time. How a system maintains that correctness under continuous mutation determines whether downstream consumers can trust those inputs without additional safeguards.

How Materialize handles mutable data

Materialize assigns each change a position on a logical timeline and evaluates queries against consistent points on that timeline. Reads are strict serializable by default, a stronger guarantee than the SQL standard’s SERIALIZABLE: it adds linearizability, so a read never observes a state older than a write that has already been acknowledged. ClickHouse offers no equivalent guarantee across tables.

  • Views advance together as their inputs advance. Results become visible only when all contributing data has reached the same logical position.
  • Transactional boundaries are preserved. Changes committed together upstream become visible together downstream, and queries that join multiple tables observe a consistent snapshot without additional annotations.

How ClickHouse handles mutable data

ClickHouse handles mutable data through append and merge. Lightweight deletes, and lightweight updates backed by patch parts make individual mutations far cheaper than full mutations were, without introducing transactional boundaries across tables.

  • Updates and deletes replicated through CDC are written as new rows in ReplacingMergeTree tables. Background merges reconcile versions by primary key and retain the most recent version.
  • This design supports high-throughput ingestion and efficient analytical storage. Until background merges complete, multiple versions of a row may remain visible. Queries can apply the FINAL keyword to force version consolidation before execution. In normalized schemas, this must be applied across each table participating in a join.
  • When FINAL is used, ClickHouse performs reconciliation work as part of query execution. Each table must be read, sorted by its primary key, and reduced to the latest version before the join can proceed. This work is not shared across concurrent queries. As query volume increases, reconciliation cost increases proportionally because each query repeats the same consolidation steps.

In workloads where many sessions issue similar lookups or entity-level reads, this repeated reconciliation becomes a primary contributor to latency and resource consumption.

CPU and memory are spent consolidating historical versions rather than evaluating business logic. The cost scales with concurrency rather than remaining amortized across the system.

Composability in practice

Composability — the ability to build complex business entities from simpler derived components without introducing coordination overhead — depends on how a system maintains relationships across layered views.

How Materialize handles composability and materialized views

In Materialize, views compose because they share a timeline and are maintained incrementally.

  • A view can depend on another view without introducing refresh scheduling or synchronization logic. As base data changes, each layer updates within the same consistent pipeline.
  • This creates a maintained dependency graph of derived state that remains internally consistent. Applications and AI systems query this graph directly.

How ClickHouse handles composability and materialized views

ClickHouse supports two forms of materialized views:

  • Incremental materialized views act as insert triggers. When rows are inserted into a source table, the view processes those inserted rows within the same batch. This model is effective for pre-aggregating append-only data. It does not maintain global consistency across existing rows in a table and does not automatically respond to updates in joined dimension tables. Moreover, the view fires only on inserts to the left-most table in its query. When a table on the right side of a join changes, the view does not update at all. Keeping a joined entity current therefore requires chaining views or rebuilding by hand.
  • Refreshable materialized views perform scheduled recomputation. At defined intervals, the system re-executes a query and replaces the target table. This aligns with reporting workloads where freshness is measured in minutes or hours. Refreshes can be ordered across views with DEPENDS ON, which prevents a layer from reading a half-updated parent but does not remove the staleness window between refreshes, and cost scales with the full dataset rather than with the change.

Both of these materialized view forms reflect ClickHouse's primary orientation toward analytical workloads. They do not provide incremental, transactionally consistent maintenance of composed business entities that span multiple mutable tables.

AI workloads as a multiplier

AI agents amplify the architectural distinction between Materialize and ClickHouse.

In Materialize - Agents connect through the PostgreSQL interface or through an MCP server and read from continually maintained state. Scaling concurrent sessions does not multiply recomputation cost because derived results are always kept current. Agents that must react rather than poll can subscribe to a view and be pushed each change as it happens.

In ClickHouse - Reconciliation work occurs at query time. As concurrent agent sessions increase, reconciliation overhead scales with them. Cross-table consistency remains dependent on merge timing and query structure. Agents discover change only by re-querying.

As AI-driven systems become centralized within business operations, maintaining coherent, up-to-date operational state becomes foundational infrastructure.

Two data systems, two different objectives

Materialize and ClickHouse are both powerful data systems. They are optimized for different objectives.

ClickHouse delivers high-performance analytical processing across large datasets and supports exploration and reporting at scale.

Materialize is designed to minimize reaction time by continuously maintaining derived operational state as source data changes. It supports applications, automation systems, and AI agents that depend on a coherent and current representation of the business. For organizations building responsive products and AI-driven workflows, reducing reaction time becomes a strategic advantage.

Better together: routing by workload

Materialize and ClickHouse are frequently deployed together. Routing each workload to the engine built for it produces lower end-to-end reaction time than either system delivers alone, because the expensive work moves from read time to write time.

The pattern is straightforward. Transactional writes land in upstream databases, or arrive as events on Kafka. Materialize consumes them through change data capture, maintains the business entities incrementally at consistent timestamps, and serves operational reads from in-memory indexes. It sinks those same pre-joined entities onward to ClickHouse through Kafka, where they become scan-optimized tables for analysis.

Materialize performs the join incrementally as updates arrive, rather than every reader performing it again from scratch. The flat table ClickHouse scans is the same derived state that answers the operational query.

Workload
Route to
Why?
Transactional writes
OLTP Database
Durable, consistent writes against a normalized schema
Operational reads
Materialize
Known access patterns and per-entity current state, served from an index at a consistent timestamp
Fixed analytical shapes
Materialize MV → ClickHouse
Aggregation maintained continuously; ClickHouse reads a small pre-bucketed result with no scan at query time
Ad-hoc analytical shapes
ClickHouse
Full-dataset scans with arbitrary aggregation that cannot be anticipated or pre-indexed


Materialize is the system of truth for current state. ClickHouse is for aggregated insight over large data.

Here's a visualization of end-to-end context assembly latency.

End-to-end context assembly latency: Materialize 253 ms and ClickHouse standalone 1.31 s on the operational query; ClickHouse via Materialize 719 ms and ClickHouse standalone 15.53 s on the analytical query.

End to end, Materialize assembles the operational context in 253 ms while holding strict serializability across every view in the result, so no read observes a partial transaction or mixes state from two logical timestamps. The pre-aggregated ClickHouse path answers the analytical query in 719 ms. Postgres leads the analytical panel at this dataset size, but it recomputes on every read, so that lead narrows as the data grows.

Note, the ClickHouse standalone bars include the batch scheduling wait that a refresh interval creates — half the interval, on average. That is 500 ms on the operational ranking here, and roughly 15 seconds on the analytical aggregate at a 30-second interval. Tighter intervals narrow the gap, at the cost of re-running the aggregation more often. That wait is the cost of keeping the joined result correct: an incremental materialized view does not update when the joined side changes, so the ranking has to be recomputed on a schedule.

Reproduction steps can be found in the reference implementation on GitHub.

info

The above chart shows single-query measurements. As concurrency increases, the two architectures separate further. Materialize does the join and the aggregation incrementally as the data changes; a read is an index lookup against a result that already exists, so the marginal cost of an additional concurrent session is close to zero and response time stays flat as sessions scale. ClickHouse performs the FINAL reconciliation inside each query, and that work is not shared between concurrent executions. The end-to-end context assembly gap widens with every additional reader.

When not to introduce Materialize

If the requirement is purely analytical — ad-hoc aggregation over the full dataset, no per-entity operational serving, no event-driven consumers — then CDC directly into ClickHouse is the simpler architecture. ClickHouse’s own pre-aggregation facilities handle most OLAP workloads without a second database in the loop.

The incremental maintenance layer, and the additional cost that comes with it, is valuable when the same system has to quickly deliver a trustworthy representation of your business right now. AI agents routinely need this for feedback loops and when interacting with humans and other agents.

The cost is hardware. Maintaining and serving these data products is continuous work, and each pre-aggregated sink is a dataflow that runs — using local memory and disk — whether or not anyone reads from it. The question is return on investment: for a given workload, does performing the join once at write time cost less than performing it on every read? For unpredictable analytical shapes, it usually doesn't. For known access patterns like those from agent tool calls, APIs, or UIs it usually does.