Executive summary

Operational databases hold the current state of a business. Snowflake's analytical engine, the warehouses and tables that dynamic and interactive tables run on, is well suited to historical analysis, large scans, backfills, training data, and other workloads that can tolerate delay.

Agents need something different when they are making operational decisions: current business objects they can retrieve quickly and combine without seeing contradictory versions of the underlying data.

This paper calls those business objects context products. A context product turns raw operational records into a maintained representation of something an agent needs to understand, such as a customer, account, order, shipment, or approval state. It may depend on one source table or many, across databases and systems. What matters is the business object it presents and the fact that it stays current as source data changes.

info

Snowflake also sells operational stores, Snowflake Postgres and hybrid tables, but neither can be the base of a dynamic table, so a context product on Snowflake is always built and served by the analytical engine, and that is the part of Snowflake this paper compares.

Snowflake can build and serve context products. A dynamic or interactive table runs its defining query on a schedule, no more often than every 60 seconds, and writes the result to storage; agents then read that result through a standard, adaptive, or interactive warehouse. In Snowflake the refresh is the transformation, and it runs on a timer. Materialize also maintains context products on one tier and serves them from another, but its transformation is continuous: it ingests the same operational change streams, updates each context product on a transform cluster as changes arrive, and serves indexed reads from dedicated serving clusters, with every read at one consistent logical timestamp. It exposes those context products to agents directly through a built-in MCP server or plain SQL, keeps external vector and search indexes current through its sinks, can push changes to agents, and can still write finished context products to Snowflake so operational and historical workloads use the same definitions.

info

The main reasons to use Materialize for an agent context layer are freshness, read-time consistency, scalable reads, and support for proactive agents. Materialize reflects an operational change in about a second, returns every context product in a query at one logical timestamp, serves indexed reads at thousands per second while the data changes with no per-query charge, and can wake an agent the moment a change is readable.

What is a context product?

A context product is a queryable business object derived from operational data and kept current as that data changes. For example, an account context product might combine the account record with open invoices, recent support activity, and current entitlements. An order data product might combine order state, inventory, payment status, and shipment events. An agent can retrieve one of these objects directly or combine several in a transaction.

A useful context product may come from a single table or from a much larger graph of joins, filters, aggregates, and window functions. The relevant questions are the end-to-end context latency, from a source commit to the moment an agent can read the result, whether related context products agree when the agent reads them, and what resources are required to serve many concurrent agents.

How the two systems maintain and serve live context

Question
Snowflake
Materialize
How is context maintained
A dynamic or interactive table refreshes on a standard warehouse.
A materialized view is incrementally updated on a transform cluster and persisted to durable storage.
How is context served
A standard, adaptive, or interactive warehouse executes the read.
A dedicated serving cluster holds indexes on the materialized view and answers reads from memory.
What drives compute
Refresh frequency plus the serving model and read concurrency.
The rate of source changes and the state held in memory and scratch disk on the transform cluster, plus index size and read concurrency on the serving cluster.
What is the minimum refresh target
60 seconds, best effort.
No scheduled refresh floor. Updates flow as source changes arrive.
What aligns data at read time
Refreshes are coordinated within a pipeline, but independently refreshed products may differ when an agent queries them.
Every query reads all referenced products at one logical timestamp.

Serving options in Snowflake

On Snowflake, a dynamic table or interactive table defines and maintains the context product. A standard warehouse performs the refresh, and TARGET_LAG specifies the desired staleness. The minimum target is 60 seconds. Snowflake treats that target as a goal rather than a guarantee, so applications must monitor actual lag and decide how to handle a miss.

Snowflake's operational stores do not change this path. Hybrid tables cannot be the base of a dynamic table or a stream, and interactive warehouses support them for surface compatibility only. Snowflake Postgres is a separate engine; its data reaches the warehouse side through data mirroring, in preview, at a refresh interval of 30 seconds or longer, or through a read-only Iceberg catalog integration. Either way the context product is a dynamic table on the analytical side, and the 60-second floor sits on top of whatever the operational store adds.

Refresh behavior depends on the SQL and the amount of source data that changes between runs. Incremental refresh is recommended when each cycle changes only a small portion of the input. Some operators, including EXCEPT, INTERSECT, and exact percentiles, require a full refresh. Stacked GROUP BY, DISTINCT, and window functions can also make a full refresh less expensive than an incremental one. ADAPTIVE refresh mode, generally available since July 30, 2026, can reinitialize after a large upstream change makes incremental work more expensive than rebuilding. When a definition uses Cortex AI functions, UDFs, or external functions, the heuristic typically skips reinitialization because re-executing those operators across every row would cost more than a fresh build.

Serving is a separate choice. Interactive warehouses are the closest fit for short, high-concurrency agent reads, so they are the fairest basis for this comparison. They change the serving behavior and cost, but they do not change the 60-second refresh floor of the maintained table beneath them.

Serving engine
Billing model
Concurrency model
Fit for agent reads
Standard warehouse
Per second after a 60-second minimum each time the warehouse resumes. Idle time is billed until suspension.
About eight full-slot queries per cluster by default. Multi-cluster configurations add billed clusters.
Works for lower concurrency. Cost rises in steps as more clusters are needed.
Adaptive Compute
Per-query billing with no idle charge. Snowflake does not publish a fixed per-query rate.
Snowflake manages the compute pool.
Useful for bursty reads. Available on Enterprise or higher. Cost rises with query volume.
Interactive warehouse
Hourly while the cluster is running, with a one-hour billing minimum and a 24-hour minimum auto-suspend setting. The Service Consumption Table lists X-Small at 0.6 credits per hour. Queries over five seconds re-run on a fallback standard warehouse and are billed there as well.
Designed for high concurrency on short queries. Multi-cluster auto-scaling is supported; each cluster that starts bills for at least one hour.
Best Snowflake fit for this workload. Cost stays flat until another cluster is required. The cache re-warms after every refresh of the tables beneath it; only 10 tables are warmed proactively.
note

The sub-30 millisecond figures cited for interactive warehouses come from a third-party benchmark on static interactive tables, not dynamic tables refreshing every minute.

Serving in Materialize

In Materialize, the context product is an incrementally updated materialized view. The recommended production layout uses three tiers of clusters. Source clusters ingest operational change streams. Transform clusters maintain the materialized views and persist their results to durable storage. Serving clusters hold indexes on those views and answer reads from memory. A single cluster can do all three, but production deployments generally separate serving so that a heavy query or a rehydrating view cannot affect agent reads, and so that each tier scales independently. Unlike Snowflake's refresh and serving warehouses, the tiers share one logical timeline: a read on the serving cluster sees exactly the state the transform cluster has produced, and the transformation runs continuously rather than on a refresh schedule.

Transform clusters are sized for the incoming change rate and the amount of maintained state. Serving clusters are sized for the indexes they hold and the read concurrency they absorb. Indexed reads do not add a per-query compute charge, so increasing the number of readers does not change the bill until the serving cluster needs to grow. In customer deployments, indexed serving clusters have handled thousands of reads per second while the underlying data changes, with tail latencies under 20 milliseconds on index reads.

Agents can reach these context products without a custom API layer. Materialize can serve context products directly using a SQL interface, and includes a built-in MCP server, currently in public preview, that runs inside the database and exposes each indexed view as a typed tool, using the index columns as the tool's lookup keys and the view's comments as its description. Materialize recommends a serving cluster and schema dedicated to agent traffic, with the agent role granted access to only those objects, so agent reads are isolated from other workloads. An agent connects to the endpoint, discovers the available context products, and calls them directly instead of generating SQL against raw tables.

Serving comparison

The table compares the serving tier each system would use for agent reads: an interactive warehouse reading dynamic tables zero-copy on Snowflake, and an indexed serving cluster on Materialize.

Dimension
Snowflake: interactive warehouse over dynamic tables
Materialize: indexed serving cluster
Read scalability while data changes
Built for high concurrency on short queries, and auto-scales by adding clusters that each bill for at least an hour. Every one-minute refresh writes micro-partitions the cache has not seen, so reads after a refresh warm lazily, and only 10 tables are warmed proactively. Published sub-30 ms figures were measured on static interactive tables, and Snowflake does not guarantee performance while caches warm.
Indexes are updated in memory as changes arrive, so a read after a change is served from the same index at the same latency. Customer deployments serve thousands of indexed reads per second while the data changes, with tail latencies under 20 ms; capacity grows by adding cluster resources.
Correctness at read time
Each table is read at its latest completed refresh, so two context products on different cycles can disagree inside one query. Target lag is a goal, not a guarantee, and a stale read looks like a successful one.
Every query, and every read-only transaction, sees all context products at one logical timestamp. Bounded staleness returns an error instead of a result when the requested bound cannot be met.
Freshness of what is served
The last completed refresh: at least 60 seconds behind the source by design, plus ingestion.
About one to two seconds behind the source commit at the default one-second timestamp interval, which can be lowered.
Cost of reads
A fixed hourly rental, falling back to a standard warehouse billed for any query over five seconds. Flat until another cluster is needed.
A fixed hourly cluster with no per-query charge. Readers do not add to the transform cluster's bill. Flat until the serving cluster needs to grow.
Query flexibility
A fixed five-second limit with re-run on a fallback standard warehouse, and a sweet spot of selective WHERE clauses with small GROUP BYs. Large joins lower concurrency.
Any SQL, with no time limit imposed by the serving tier. Indexed lookups by key are the fast path; an ad hoc join across context products runs as a one-shot dataflow at lower throughput. Long-running queries can be isolated on their own cluster.
Governance
Masking and row access policies attached to the tables as policy objects, enforced regardless of warehouse type.
Row-level and column-level access through RBAC, entitlement tables, and views. This is currently a documented pattern rather than a policy object, and views have no security_barrier.

End-to-end context latency

End-to-end context latency starts when the operational database commits a change. Both systems must ingest that change, update the relevant context product, and serve the result. The difference is the number of stages, the refresh floor, and what happens when the system cannot meet its target.

Stage
Snowflake
Materialize
Commit to raw data
Snowpipe Streaming can ingest appends in a few seconds. Updated rows handled through MERGE require a warehouse. Production CDC pipelines often batch for longer to control credit use. The Openflow PostgreSQL connector, for example, journals changes and merges them into destination tables on a CRON schedule, which is when warehouse cost accrues.
Native sources for Postgres, MySQL, SQL Server, and Kafka. The benchmark measured 0.8 seconds from commit to the replicated table.
Raw data to context product
Dynamic or interactive table with a minimum 60-second target lag. The target is best effort, and one refresh must finish before the next begins.
Incremental view maintenance. The benchmark measured 1.0 second through a four-table context product under serializable isolation and 2.0 seconds under strict serializable isolation on a one-second source tick.
Context product to agent
A warehouse executes the read. Warm-cache reads can be sub-second; a recent refresh or warehouse resume can make the first read slower.
An indexed read on the serving cluster. The Emulator benchmark measured 3 ms p50 and 9 to 13 ms p99 at 83 reads per second on a dedicated serving cluster, and 3 to 4 ms p50 at 500 reads per second.

In Snowflake's best case, end-to-end latency includes a few seconds of ingestion, at least 60 seconds of target lag, and the final read. Production latency may be longer when ingestion is batched or a refresh falls behind. In Materialize, end-to-end context latency is about one to two seconds at the default one-second source timestamp interval, and that interval can be lowered.

The more important distinction is enforceability. Snowflake reports whether a target lag was met, but an application should not assume that every read is within the target. Materialize can enforce a bounded-staleness requirement at query time through its bounded staleness isolation level. It returns data from a timestamp within the requested bound, never blocks waiting for inputs to catch up, and returns a serialization error if the bound cannot be met. The agent can then avoid acting on data of unknown age.

A one-minute Snowflake target also has serious cost implications. Under continuous CDC, the refresh warehouse always has new work and may never suspend. Cloud services check for changes on each cycle. Interactive cache warming must also keep up with the new micro-partitions produced by refreshes.

Read consistency across context products

Snowflake and Materialize have different approaches to consistency; these choices ultimately impact agent effectiveness and token efficiency. Snowflake coordinates the inputs to a pipeline refresh. Materialize coordinates the context products returned by a query. For an agent choosing an action, the query-time guarantee is the one that determines whether the assembled context describes a single state of the business.

Within a Snowflake pipeline refresh, every table reads its upstream inputs at a coordinated data timestamp. This is stronger than independently scheduled streams and tasks. The guarantee ends with the refresh, however. An ad hoc query reads the latest committed version of each table. If two context products refresh on different cycles, an interactive warehouse can join versions that represent different points in time.

Pipeline boundaries add another qualification. A downstream dynamic table may consume stale data from an upstream object it does not control. The refresh can still report success. Snowflake recommends a boundary around views that a pipeline owner does not control, which is common when different teams publish shared context products. Repeated refresh failures are surfaced as increasing staleness, and a dynamic table is automatically suspended after five consecutive failures.

Materialize assigns logical time as changes enter the system and preserves that time through computation. A query that reads several context products sees all of them at one timestamp. This remains true across isolation levels; the isolation choice changes the tradeoff between recency and latency, not whether the query is internally consistent.

Requirement
Snowflake
Materialize
Products agree at read time
Only when they were aligned by the same pipeline refresh. An agent query across independently refreshed products has no equivalent guarantee.
Yes. Every query uses one logical timestamp across all referenced products.
Products agree across team boundaries
A boundary can decouple refreshes, and stale input can still produce a successful refresh.
Independent streams share one logical timeline.
Staleness requirement
A target that must be monitored after refresh.
A query-time contract. The query errors if the bound cannot be met.
Read after an upstream write
The write becomes visible after ingestion and refresh, which can take minutes.
Strict serializable isolation stays within seconds of wall-clock time. Real-time recency, a private preview option on strict serializable sessions that adds latency, guarantees the next read includes everything the upstream source had committed when the query arrived.
Behavior when the system is behind
Serves the last successful version while lag increases.
Depends on the isolation level the application chooses. Strict serializable waits for the required timestamp, bounded staleness rejects the read, and serializable serves the latest consistent state.
note

Materialize defaults to strict serializable isolation and recommends starting there. Use serializable isolation for latency-sensitive agent tool calls that do not need to wait for an update into Materialize to be reflected in the agent's context. When the next read must reflect the agent's own upstream write, enable real-time recency, currently in private preview, on a strict serializable session. When the application would rather fail than wait, use bounded staleness. You can read more about isolation levels here.

Why agent workloads raise the bar

  • Agents often write to an operational system and immediately read context to decide what to do next. A minute of lag can break that feedback loop and make it impossible to build interactive agents with humans in the loop.
  • Stale data can cause an incorrect action, not merely an outdated display. A delayed dashboard is inconvenient; a refund approved against an old account state can be wrong.
  • Agents combine several business objects at the moment of decision. Those objects need to describe the same point in time.
  • An explicit freshness failure lets the application pause, retry, or escalate. A successful query that silently returns old data does not.
  • Concurrency comes from many agents issuing small reads, rather than a smaller number of analysts running exploratory queries.
  • Prepared context products reduce tokens as well as database work. They replace wide raw payloads, repeated text-to-SQL attempts, and polling with a direct call that returns only the context the agent needs.
tip

This guide goes into more detail on how a live, trustworthy context layer improves agent cost, speed, and task success.

Push-based agents

Some agent architectures avoid polling to minimize reaction time and save tokens spent asking the same question multiple times. A change in the business, such as a payment failing or an order shipping, should wake the agent, and the agent should then read the rest of its context as of the same moment. That asks two things of the context layer: a way to deliver changes as they happen, and a way to tell the consumer when what it has received is complete.

Snowflake delivers changes out of a context product as a batch feed from a stream. A stream on a dynamic table works only with incremental refresh, and a reinitialization delivers every row difference at once. A triggered task can consume the stream and call a notification integration. Triggered tasks fire at most every 30 seconds by default and every 10 seconds with a parameter change, and scheduled alerts run at most once a minute. The Openflow Connector for Snowflake to Kafka, in preview, consumes one stream per connector and emits change records to a topic without a schema and without schema evolution, on an Openflow runtime billed per second with a 60-second minimum, from 0.11 credits per hour for the smallest Snowflake-hosted node, plus a warehouse the connector uses to read the stream. Its setup page exposes no polling-interval parameter. There is no primitive by which a client subscribes to a changing query result. End to end, a push consumer learns of an operational change after ingestion, the 60-second refresh floor, and the trigger or poll interval, on the order of one and a half to two minutes.

Materialize delivers changes with SUBSCRIBE, which streams inserts and deletes to a view, materialized view, source, or ad hoc query over the PostgreSQL wire protocol. Each update carries a logical timestamp, and progress messages report when a timestamp is complete, so a consumer can act on a consistent frontier and distinguish a quiet period from a stall. For many consumers, a Kafka sink emits the same changes with an upsert or Debezium envelope and exactly-once delivery by default.

tip

The Materialize MCP server is a pull interface today, so a push-driven agent is fed by a SUBSCRIBE consumer or a Kafka sink rather than by the MCP endpoint. Each subscription is its own dataflow on the serving cluster, so a large number of direct subscribers is better served by one Kafka sink and ordinary consumers.

Which workloads belong in each system

Use Materialize when
Use Snowflake when
Agents repeatedly retrieve the same business objects, such as a customer, account, order, or shipment.
A query is exploratory and needs to scan historical data.
A task combines several context products and requires them to agree at read time.
The workload is a backfill, model training set, evaluation set, or other large batch.
The agent writes to an operational system and needs the next read to reflect that change.
Minutes of staleness are acceptable and reads are infrequent.
The application must know whether the result is fresh enough to support an action.
A human is exploring data with text-to-SQL.
The workload consists of many concurrent, short reads.
The question is genuinely novel and no maintained business object already answers it.

A practical routing rule is to use Materialize for named, maintained context products and Snowflake for novel analytical questions. If a context product already answers the question, the agent should call it instead of generating SQL against raw tables.

For Materialize reads that combine multiple products, define a composite context product or issue indexed reads inside one read-only transaction. The first statement in a read-only transaction fixes which schemas later statements can reference, so place products that agents read together in the same schema. An unindexed ad hoc join creates a one-time dataflow and has materially lower throughput.

A combined architecture

Materialize and Snowflake can consume the same operational database and Kafka change streams. Materialize maintains the current business objects used by agents and operational applications. Snowflake retains history and serves analytical workloads. Rather than create two parallel pipelines, Materialize can deliver finished context products to Snowflake. There are two paths:

  1. A native Iceberg sink writes exactly-once updates to Iceberg tables in Amazon S3 Tables, which Snowflake reads as external Iceberg tables.
  2. A bulk export to Amazon S3 can be loaded with COPY INTO on a schedule.

Either allows batch scoring, business intelligence, and historical analysis to use the same definitions as the live agent path.

This design avoids maintaining separate transformation logic for live and historical systems. It also removes the need to copy Snowflake results back into an operational serving layer before an agent can use them. Both systems remain active, but they are active for different reasons: Materialize is sized for the rate of change and maintained state, while Snowflake runs the warehouses required to refresh and serve its copies.

The cost of serving fresh context

Snowflake and Materialize charge for different parts of the workload. In Snowflake, the refresh warehouse is one bill and the serving engine is another. Serving cost depends on whether reads run on a standard warehouse, Adaptive Compute, or an interactive warehouse. Materialize charges per second for each cluster, so the bill is the transform and serving clusters that maintain the context products and serve their indexed results.

For a continuously changing context layer with a one-minute Snowflake target lag, the refresh warehouse is unlikely to suspend. That makes refresh a fixed hourly cost even if no agent reads the result. The serving line then behaves differently by engine:

  • A standard warehouse adds capacity in steps. A continuously active reader can keep the warehouse running, and another cluster is required when concurrent queries exceed the capacity of the existing cluster.
  • Adaptive Compute bills per query and has no idle charge, so cost rises with read volume. Snowflake does not publish a fixed per-query rate.
  • An interactive warehouse is effectively a fixed hourly rental while active. It remains flat until another cluster is required, with a separate standard warehouse billed when a query exceeds the five-second limit.

Materialize's cost changes when source change volume or maintained state requires a larger transform cluster, or when read concurrency requires a larger serving cluster, not per query.

For the same interactive workload Materialize is typically less expensive, but the architectural differences in freshness and consistency matter more.

Conclusion

Snowflake can maintain and serve agent context, particularly when a team values platform consolidation and can tolerate at least a minute of best-effort refresh lag. Its interactive warehouse is the right Snowflake serving option for short, concurrent reads.

Materialize is the stronger fit when an agent needs context that reflects operational changes within seconds, when several business objects must agree at the moment they are read, or when the application must reject data that is too stale to support an action. A combined architecture lets Materialize serve that live context while Snowflake remains the system for history, exploration, and large-scale analytical work.