Skip to content

Why Snowflake can’t match ClickHouse Cloud for real-time analytics

tom schreiber headshotlio headshot singapore
Sep 10, 2026 · 15 minutes read

TL;DR

Real-time systems vary dramatically in the cost and efficiency of making incoming data query-ready. In this series, we trace the path from data arrival to current answers, showing how it shapes preparation cost, query cost, and query runtime.

Here, we follow ClickHouse Cloud and Snowflake using their recommended real-time stacks while ingesting 113.2 billion quotes and running queries. ClickHouse Cloud delivered 412× better end-to-end performance per dollar.

This is Part 2 of our CostBench series.
Other parts: Methodology · Databricks · BigQuery · Redshift
Coming next: Why ClickHouse Cloud won

From fresh data to fast answers

Real-time analytics has to stay fast while fresh data keeps arriving. CostBench tests this directly: queries run throughout continuous ingestion, and their answers must include newly arrived data. Efficient preparation lowers the cost of keeping that data query-ready and leaves less work for queries, reducing their cost and runtime.

Columnar storage lets queries skip unused fields; ordering lets drill-downs skip unrelated quotes; current pre-aggregations let interactive aggregations combine prepared summaries. The animation below shows how this fresh-data path changes the scanning and aggregation left for queries as preparation catches up or falls behind.

CostBench measures ① preparation cost, ② query cost, and ③ runtime, then combines them into one end-to-end performance-per-dollar score.

This article follows those three effects through the ClickHouse–Snowflake comparison, from preparing incoming data to serving current answers.

The workload and the result

ClickHouse Cloud delivered 412× better end-to-end performance per dollar than Snowflake in this continuous-ingestion workload.

Both systems used their recommended real-time stack and low-latency ingestion path. CostBench streamed 113.2 billion stock-market quotes at a target of 1 million rows per second, using matching sorting or clustering keys and daily pre-aggregations by stock symbol. Throughout ingestion, four interactive aggregate queries ran every ten minutes; two drill-down queries over raw quotes ran every hour. Every query covered the history ingested so far, including newly arrived quotes. Read-side compute was matched at approximately 16 CPUs, with query-result caching disabled.

CostBench calculates its end-to-end performance-per-dollar score using the formula shown in the diagram below: Score = (① preparation cost + ② normalized query cost) × ③ accumulated query runtime.

Preparation cost covers the complete fresh-data path. Normalized query cost prices measured query runtimes at the applicable read-side compute rates. Accumulated query runtime is the sum of query durations. Lower scores are better.

HOW DID WE MEASURE ① ② ③? (click to expand)

SHARED HARNESS

Both systems used the same source files, schema, row decoder, workload generator, AWS EC2 m6i.8xlarge client host, rate controller, scheduler, timing, and result recorder. Only the destination-specific delivery adapter changed. Part 1 describes the shared methodology.

DATASET AND PREPARATION

The complete NBBO dataset contains 113.2 billion narrow, 12-column rows. Raw tables used (sym, t), stock symbol and event timestamp; daily summaries used (sym, day), stock symbol and day. The summaries maintained the counts, sums, and price minima and maxima used by the aggregate queries.

CONTINUOUS WORKLOAD

The client paced fresh rows toward 1 million rows per second while four interactive aggregate queries ran every ten minutes and two drill-downs every hour. Every query covered the history ingested so far, including the newest quotes. This simulates fresh data being generated continuously and becoming query-ready as it arrives. It measures the cost and performance of sustaining that workload, rather than the speed of bulk-loading or backfilling an existing dataset.

RECOMMENDED STACKS AND SIZING

Both systems used vendor-recommended low-latency components and native implementations of the same preparation requirements. ClickHouse Cloud used one 16-CPU, 64-GiB read node; Snowflake used a Small Interactive Warehouse and a Gen2 Small fallback, each treated as approximately 16 CPUs because Snowflake does not publish CPU counts. This sizing draws on SELECT.dev and an independent Gen2 inspection.

① PREPARATION COST

The complete 113.2-billion-row ingest includes all metered ingestion and preparation work. ClickHouse’s cost includes both 2-CPU nodes in its smallest calibrated high-availability ingest service. Snowflake’s separately metered Snowpipe Streaming and serverless MV refresh are both included.

② QUERY COST AND ③ RUNTIME

Query cost prices each accepted query’s full client-visible duration at the applicable read-side rate. Runtime sums those durations over the same active-ingestion workload, aligned by row count. These normalized query costs are separate from complete warehouse invoices. The query-comparison and pricing notes below give the accepted counts, rates, and exclusions.

TARGET VERSUS OBSERVED RATE

The target implies about 28 hours for 100 billion rows. Observed throughput averaged approximately 0.86 million rows/s for ClickHouse and 0.90 million for Snowflake. They reached 100 billion rows after roughly 32 and 31 hours, and completed 113.2 billion rows after roughly 37 and 35 hours, respectively. Client pacing, parallel streams, and batching targeted an exact rate but could not guarantee one.

REPORTING WINDOW

Per-query latency charts stop at 100 billion rows. Preparation costs cover the complete ingest; accumulated query runtime and cost use the full accepted active-ingestion observations aligned by row count. Displayed totals are rounded.

ClickHouse Cloud led in all three measured components:

① Preparation cost: $28.69 versus $79.42.
② Normalized query cost: about $0.05 versus $15.99.
③ Accumulated query runtime: 1.03 minutes versus 2.13 hours.

The charts below track how those differences accumulated while data arrived.

The score breakdown below brings those components together: ClickHouse Cloud’s 3.32× lower combined preparation and normalized query cost and 124× lower accumulated query runtime multiply to produce its overall performance-per-dollar advantage.

PRICING, FORMULAS, AND THE 412× SCORE (click to expand)

PRICING BASIS

The tested Enterprise pricing in AWS us-east was $3 per Snowflake credit and $0.3903 per ClickHouse Cloud compute unit (CU) per hour. Snowflake’s serverless charges use its metering history. Displayed values below are rounded; the accepted summary uses full-precision inputs.

① COMPLETE PREPARATION COST

This covers ingestion and preparation of all 113.2 billion rows.

ClickHouse Cloud: 2 CUs × 36.75 hours × $0.3903/CU-hour = $28.68705. This includes both nodes of the HA ingest service.

Snowflake ingestion: Snowpipe Streaming processed 4.6762 TiB, metered at 17.71783 credits under the 0.0037-credits-per-uncompressed-GB rate. Multiplying the unrounded credits by $3 gives $53.15348. Ingest-time clustering is included; no ingest warehouse was used.

Snowflake refresh: 8.75553 metered credits × $3/credit = $26.26659. Total preparation cost: $53.15348 + $26.26659 = $79.42007.

② NORMALIZED QUERY COST

Each accepted query is priced as its full client-visible duration × the applicable per-second read-side rate.

ClickHouse Cloud: 8 CUs × $0.3903/CU-hour × (11.361s aggregate + 50.466s drill-down) ÷ 3,600 = $0.05362.

Snowflake Interactive-priced work: (946.509s aggregate + 74.815s drill-down) × 1.2 credits/hour × $3/credit ÷ 3,600 = $1.02132.

Snowflake fallback-priced work: 6,653.660s aggregate × 2.7 credits/hour × $3/credit ÷ 3,600 = $14.97074. Total normalized query cost: $1.02132 + $14.97074 = $15.99207.

Fallback boundary: The elapsed-time proxy assigns jobs above five seconds to Gen2 Small for their full duration and all others to Interactive Small. It excludes standing fallback capacity, idle capacity, minimum billing, and an additional Interactive charge for fallback-priced jobs. The allocation is a cost model, not a reconstruction of which warehouse physically executed each job.

③ ACCUMULATED QUERY RUNTIME

ClickHouse Cloud: 11.361s aggregate + 50.466s drill-down = 61.827s.

Snowflake: 7,600.169s aggregate + 74.815s drill-down = 7,674.984s.

COMPARISON BOUNDARY

① covers the complete ingest. ② and ③ use the accepted active-ingestion sets aligned by row count: 209 × 4 aggregate queries and 35 × 2 drill-downs per system. Later post-ingestion observations and database storage are excluded. Query cost is normalized to accepted query work; it is not the complete warehouse invoice.

FINAL SCORE

ClickHouse Cloud: ($28.68705 + $0.05362) × 61.827 = 1,776.9494.

Snowflake: ($79.42007 + $15.99207) × 7,674.984 = 732,286.6479.

Relative score: 732,286.6479 ÷ 1,776.9494 = 412.103× using the full-precision inputs.

412× better real-time performance per dollar

That’s what ClickHouse Cloud delivered compared with Snowflake in CostBench under continuous load. See what it can do for your data - sign up today.

Try ClickHouse Cloud

All benchmark code and results are available in the CostBench repository. The stock-quotes dataset requires a separate data license, so the data itself cannot be redistributed.

To explain the result, we will follow the same path as the data: preparation first, then query serving.

How ClickHouse Cloud prepares incoming data

The benchmark used a dedicated ClickHouse Cloud ingest service with two 2-CPU nodes for high availability - the smallest HA configuration that sustained the target during calibration. The shared client sent rows through asynchronous inserts built into each node.

As shown below, those same two nodes handled ① columnar storage, ② ordering raw data, and ③ ordered pre-aggregation, plus background merges, on four CPU cores in total.

① Store in columns and ② order data: When an ingest node flushes its asynchronous-insert buffer, it sorts the raw quotes by the MergeTree table’s (sym, t) key - stock symbol and event timestamp - and writes an ordered data part.

③ Order and pre-aggregate data: In parallel, the same node runs the incremental MV’s query over the incoming data block in memory, computes aggregate states, and sorts the results by the AggregatingMergeTree table’s (sym, day) key - stock symbol and day - before writing an ordered data part containing the pre-aggregated data.

Background merges consolidate parts in both tables.

The result: raw data and pre-aggregations advance together from the same flushed insert block, without a separate refresh cycle.

HOW MUCH WORK DID THE FOUR-CORE INGEST SERVICE HANDLE? (click to expand)

The writer-utilization results show the two-node service sustaining ingestion alongside background maintenance. CPU usage remained around 3.1 of its 4 available cores, tracked memory stayed within capacity, background merges processed several million rows per second, and the maximum active-part count per partition stayed around 100.

Both nodes were retained for high availability, so the preparation cost includes the complete two-node deployment.

We now follow the same preparation tasks through Snowflake, where ingestion and materialized-view refresh run in separate services.

How Snowflake prepares incoming data

The benchmark used Snowpipe Streaming’s high-performance architecture, which places a managed server-side ingestion buffer between application writes and the Interactive Table.

As shown below, Snowpipe Streaming handles ① columnar storage and ② ordering raw data, while a separate serverless refresh service handles ③ ordered pre-aggregation.

① Store in columns and ② order data: Snowpipe Streaming writes rows directly into an Interactive Table. With CLUSTER_AT_INGEST_TIME=TRUE, it pre-clusters incoming rows on the shared (sym, t) key before writing them into micro-partitions - Snowflake’s columnar storage units.

③ Order and pre-aggregate data: A separate Snowflake-managed serverless service refreshes the Interactive MV asynchronously from that table. We configured the view with a (sym, day) clustering key, matching the sorting key of ClickHouse’s pre-aggregation table. Snowflake controls when refreshes run and how much compute they use; users cannot configure the refresh schedule or size the refresh compute.

The result: the separate refresh cycle can leave Snowflake’s pre-aggregations behind its raw data.

WHY THESE INGESTION PATHS, AND HOW WERE THEY BUFFERED? (click to expand)

THE SAME INGESTION PROBLEM

Applications produce small, frequent writes that must be combined into efficient storage writes. This benchmark measures direct application-to-table ingestion, using server-side buffering in both Snowpipe Streaming and ClickHouse asynchronous inserts.

SNOWFLAKE’S MANAGED SERVICE

Clients open channels against a PIPE object. The high-performance ingestion service handles buffering, validation, configured transformations, and optional pre-clustering before committing rows. Snowflake manages the ingestion compute and bills it separately by uncompressed volume.

CLICKHOUSE’S NATIVE PATH

Ordinary INSERT requests with async_insert enabled are buffered on each receiving node. An adaptive flush timeout responds to incoming traffic. Ordering, pre-aggregation, and insert-path transformations run on those nodes; a dedicated ClickHouse Cloud ingest service can scale independently from reads while sharing the same stored data.

SHARED PACING

Both destinations used the same Parquet source, row decoder, client compute, rate controller, and eight-worker parallelism. Destination-specific batching adapted delivery to each API.

CLICKHOUSE BATCHES

The client sent 3,000-row batches through asynchronous inserts. With the run’s default buffering settings, a node flushed at the first of three thresholds: 100 MiB buffered, an adaptive timeout between 50 milliseconds and 1 second, or 450 queued insert queries.

SNOWFLAKE BATCHES

Each worker called append_row through its own channel. Earlier stream-preview evidence for this setup shows the SDK choosing file mode and grouping calls into NDJSON batches averaging approximately 61,500 rows. Across eight channels, that produced about 14.6 file uploads per second before further server-side buffering.

BATCH-SIZE BOUNDARY

The 3,000-row and approximately 61,500-row figures describe client delivery batches. Both systems buffered them again server-side, so these figures do not specify final storage-write sizes.

RETRIES AND RECOVERY

Snowpipe Streaming’s offset tokens record committed channel progress. A custom application retrieves the last token, maps it to its source, and resumes from the next record; Snowflake’s Kafka connector handles that mapping for Kafka partitions. ClickHouse supports insert deduplication for retries, including dependent materialized views.

WHERE CLICKPIPES FITS

Direct application writes are compared here. For Kafka, the corresponding integrations are Snowflake’s Kafka connector and Kafka ClickPipes; for object-storage files, classic Snowpipe and Object Storage ClickPipes. Those paths include an external-source integration beyond the direct-write boundary measured here.

STORAGE CONTEXT

In the earlier configuration, at roughly 113 billion rows, Snowflake’s raw Interactive Table occupied 2.9 TiB, versus 701 GiB for its standard table and 362 GiB for ClickHouse’s raw table, roughly four and eight times as much. These are earlier-study footprints, and database storage costs are excluded from this score.

What this means for freshness and preparation cost

Pre-aggregation lag

ClickHouse updates summaries during inserts; Snowflake refreshes them asynchronously. The chart below shows the resulting raw-to-summary lag: zero for ClickHouse in this setup; Snowflake’s plotted lag averages about 1.4 minutes and reaches about 2 minutes.

This measures summary freshness: Snowflake still returns current answers by including newer rows at query time.

HOW WAS PRE-AGGREGATION LAG MEASURED? (click to expand)

SNOWFLAKE SERIES

The MV-lag series uses 2,072 active one-minute behind_by samples. Poll timestamps were aligned to raw row count by linear interpolation between 208 active dashboard observations.

SMOOTHING AND READOUTS

The reported average and maximum come from a centered 61-sample rolling mean: 1.372 and 2.033 minutes, rounded to 1.4 and 2.0 minutes. The displayed trend adds a centered 11-sample rolling mean and shape-preserving interpolation. Its interactive readout follows that displayed trend at the selected row count.

CLICKHOUSE BASELINE

The zero line is a benchmark-semantic baseline rather than a separately polled provider metric. The raw table and incremental MV consume the same flushed insert block, with no independent refresh interval between them.

ClickHouse kept pre-aggregations current during ingestion; Snowflake’s refresh lag shifted catch-up work onto queries.

We examine that extra work in the serving comparison below; first, the next chart accounts for preparation cost.

Cost of keeping incoming data query-ready

ClickHouse handles ① columnar storage, ② ordering raw data, and ③ ordered pre-aggregation natively within its engine. Snowflake splits the same work across separately charged services. The chart below compares their accumulated preparation costs.

ClickHouse’s complete ingest service cost $28.69. Snowflake’s preparation totaled $79.42: $53.15 for Snowpipe Streaming’s columnar storage and ordering (① ②), plus $26.27 for ordered pre-aggregation through materialized-view refresh (③), about 2.8× as much.

ClickHouse handled columnar storage, ordering, and pre-aggregation in one ingest service; Snowflake’s separately charged services cost 2.8× as much.

Now we follow the prepared raw data and summaries into query serving.

How ClickHouse Cloud serves queries

Ordered raw data lets drill-downs skip unrelated rows; pre-aggregations let interactive aggregations combine prepared results instead of recalculating them from individual quotes. The diagram below shows both paths through ClickHouse Cloud’s read service: one node with 16 CPUs and 64 GiB of memory, matching the estimated CPU count of Snowflake’s Small warehouse.

Drill-downs: Queries prune ordered raw data in the event-level MergeTree table. Filtering by symbol, the leading column of its (sym, t) sorting key, lets the read service skip unrelated quotes.

Interactive aggregations: Queries read current pre-aggregations from the AggregatingMergeTree table, combining prepared counts, sums, minima, and maxima from a much smaller set of daily summary rows. No refresh catch-up work is needed.

The result: drill-downs prune ordered raw data; interactive aggregations read summaries kept current during ingestion.

Snowflake uses the same two query paths, with additional work when its summaries lag.

How Snowflake serves queries

The diagram below shows Snowflake’s Small Interactive Warehouse serving both workloads, with an estimated 16 CPUs and approximately 600 GB of local SSD cache.

Drill-downs: Queries prune ordered raw data in the Interactive Table directly. Its (sym, t) clustering, applied during ingestion, lets them skip unrelated quotes when filtering by symbol.

Interactive aggregations: Queries target the Interactive MV and catch up on read by combining its summaries with rows added to the Interactive Table since the last refresh. The answer therefore includes current data.

Timeout and fallback: Interactive Warehouses cancel queries that exceed five seconds; the limit can only be lowered. We configured a separate Gen2 Small standard warehouse, also estimated at 16 CPUs, to receive eligible timed-out queries through Snowflake’s automatic fallback mechanism.

HOW ARE SNOWFLAKE’S CATCH-UP AND FALLBACK PATHS INTERPRETED? (click to expand)

CURRENT-ANSWER CONTRACT

Queries against an Interactive MV include the rows added to the base table since its last refresh. The amount of newer data grows between refreshes and shrinks when a refresh catches up, explaining the rising-and-reset pattern in the aggregate curves.

FALLBACK CONFIGURATION

The tested Interactive Warehouse used a five-second limit and a separate Gen2 Small fallback warehouse for eligible queries. The benchmark’s normalized-cost model uses elapsed time as a pricing proxy; it does not establish which warehouse physically executed each query.

ATTRIBUTION RULE

Each accepted query with a full client-visible duration strictly greater than five seconds is priced for its entire duration at the Gen2 Small rate. Queries at or below five seconds use the Interactive Small rate. Exactly five seconds remains Interactive-priced. Each query belongs to one bucket, without an additional Interactive charge for fallback-priced work.

OBSERVED ALLOCATION

Of 836 aggregate executions, 477 (57.1%) were above five seconds; all 70 drill-downs were at or below it. A query at or below the threshold could still have used fallback in reality, so the proxy can undercount fallback.

COST EXCLUSIONS

Standing fallback capacity, minimum billing, idle capacity, and an additional primary-warehouse charge for fallback-priced queries are excluded. Full-duration timing is retained; no query phase is removed from latency or normalized cost. The pricing note below provides the rates and calculation.

The result: drill-downs prune ordered raw data; interactive aggregations catch up on read when summaries lag.

What this means for query performance and cost

Drill-downs over ordered raw data

Both systems order raw data as it arrives, so drill-downs can prune unrelated data. D1 and D2 query one stock’s growing history directly: hourly price summaries and a risk-and-liquidity profile. The chart below follows this raw-data path, which bypasses the materialized views.

ClickHouse Cloud is yellow; Snowflake is blue.

HOW WERE QUERY LATENCIES AND ACCUMULATED RESULTS COMPARED? (click to expand)

QUERY DEFINITIONS

Part 1 explains the four aggregate queries A1–A4 and two drill-downs D1–D2, including how newly ingested quotes contribute to their answers. Both systems used the same query semantics and schedule.

CACHE POLICY

Query-result caching was disabled, so every measured query ran. Underlying data caches were allowed to remain warm. Both systems used the read-side sizing described in the methodology note.

TIMING

Latency and accumulated runtime use each query’s full client-visible duration. Per-query median, P99, and maximum statistics summarize unsmoothed observations through 100 billion rows.

LATENCY CHARTS

Each system is plotted against its own observed row counts, rather than equal iteration numbers or interpolation between systems. Aggregate trends use a centered seven-observation rolling median; drill-down trends use a centered five-observation rolling median. The aggregate chart retains its Snowflake-only Tukey upper-fence rule, with excluded points retained in the source and summary. Drill-downs have no outlier filter.

INTERACTIVE READOUTS

Values beneath the charts follow the displayed trends at the selected row count. Logarithmic scales keep milliseconds and seconds readable together; Linear shows absolute differences. Each chart has independent playback and row-position controls.

ACCEPTED ACCUMULATED WORKLOAD

Runtime and normalized query cost use 209 four-query aggregate batches and 35 two-query drill-down batches per system: 836 + 70 = 906 executions. Observations are aligned by ingestion progress. The first complete-dataset observation belongs to active ingestion; later post-ingestion observations are excluded.

ACCUMULATED CHART

Recorded durations are added at their aligned row positions, without smoothing or interpolation between observations. The total is the sum of query durations, not the elapsed ingestion time. Its aggregate component uses maintained pre-aggregations; the alternative raw-table test described later is outside the headline score.

ClickHouse Cloud:

  • 722.5 ms median - 1.38× faster than Snowflake
  • 1.15 s P99 - 2.06× faster
  • 1.18 s maximum - 2.17× faster

Accumulated runtime was 50.47 seconds. Latency increased more gradually and remained lower at larger data volumes.

Snowflake:

  • 993.5 ms median
  • 2.37 s P99
  • 2.56 s maximum

Accumulated runtime was 74.81 seconds. Latency rose more steeply as data accumulated; all 70 executions remained below the five-second fallback threshold.

WHAT DOES SNOWFLAKE’S SERVING CACHE CHANGE? (click to expand)

EARLIER DIAGNOSTIC EVIDENCE

Snowflake documents cache warming as a non-blocking background process. Earlier query profiles for this workload reported zero or negligible remote reads during active ingestion and a median 100% of bytes served from cache. At roughly 75 MB/s of ingest, the queried working set fit within Small’s approximately 600 GB cache and warming kept pace. These diagnostics describe the earlier configuration, rather than separately measuring cache hits for this post’s headline run.

WHAT THAT SHOWS

The earlier diagnostic represented a favorable cache case. Having the relevant data local still leaves the work of reading and filtering the growing raw table.

WORKING-SET CAPACITY

Even the largest Interactive Warehouse, 4X-Large, has a finite documented 44 TB cache. A working set that exceeds cache capacity requires more remote reads. Warehouse sizing therefore affects both cache capacity and cost.

WARMING THROUGHPUT

Snowflake documents roughly 300–400 MB/s of warming throughput even for X-Small, with larger warehouses warming faster. That exceeds the earlier workload’s roughly 75 MB/s ingest rate. At higher source rates, recently arrived data may require remote reads even when the total working set still fits.

SIZING IMPLICATION

The Interactive Warehouse must be sized for both the data queries touch and the rate at which new data arrives. ClickHouse’s query path reads the ordered MergeTree table without a separately populated Interactive Warehouse serving cache.

Across the drill-down workload, ClickHouse Cloud was 1.48× faster overall.

Interactive aggregations over ordered pre-aggregated data

Daily pre-aggregations let A1–A4 combine prepared counts, sums, and price minima and maxima. A1–A2 filter the ordered summaries by symbol; A3–A4 read across all symbols. ClickHouse reads current summaries; Snowflake must also include newer rows. The chart below shows the resulting latency gap as data accumulates.

ClickHouse Cloud:

  • 13 ms median - 801× faster than Snowflake
  • 42 ms P99 - 533× faster
  • 111 ms maximum - 218× faster

Accumulated runtime was 11.36 seconds.

Snowflake:

  • 10.41 s median
  • 22.20 s P99
  • 24.17 s maximum

Snowflake’s sawtooth curves rise as rows accumulate between refreshes and fall when refreshes catch up. Accumulated runtime was 2.11 hours. Under the benchmark’s five-second fallback proxy, 477 of 836 executions (57%) were priced at the fallback rate.

Across the interactive-aggregation workload, ClickHouse Cloud was 669× faster overall.

Accumulated query cost and runtime

Those per-query differences accumulate: interactive aggregations account for most of the gap. The charts below combine both workloads and price their measured runtimes using the benchmark’s read-side cost model.

ClickHouse Cloud accumulated 1.03 minutes of query runtime and Snowflake 2.13 hours. Their normalized query-serving costs were about $0.05 and $15.99, respectively. These are normalized costs for the query work, not complete warehouse invoices.

Across the query workload, ClickHouse Cloud was 124× faster overall, with 298× lower normalized query cost.

From the field: Appcues

Appcues’ migration from Snowflake to ClickHouse Cloud shows the same full-path efficiency in production: faster queries, fresher data, and lower analytics spend for its customer-facing dashboards. “Page load time has to be practically instant,” says Chris Brookins, VP of Engineering. Its Snowflake-and-Airflow stack rolled up data every five to ten minutes, delaying fresh results and adding infrastructure to maintain. Computing aggregates during inserts let the team retire its Airflow infrastructure.

P95 query latency fell from over 20 seconds to under 2 seconds, and newly arrived events became queryable in about 5 seconds, down from ten minutes or more. Analytics spend fell 23%, even as Appcues added workloads and features. Read Appcues’ migration story.

Snowflake can’t match ClickHouse Cloud for real-time analytics

While fresh data kept arriving, ClickHouse Cloud outperformed Snowflake across the complete workload:

① Preparation cost: 2.8× lower for ingestion, ordering, and pre-aggregation.
② Normalized query cost: 298× lower for the matched queries.
③ Accumulated query runtime: 124× lower across both query workloads.

The final chart brings these results together, plotting combined preparation and normalized query cost against accumulated query runtime as fresh data arrives.

Up is lower total cost; right is lower accumulated query runtime.

ClickHouse Cloud delivered 412× better end-to-end performance per dollar while ingesting fresh data and serving current answers.

The biggest serving advantage came from interactive aggregations. ClickHouse read current summaries; Snowflake had to combine its summaries with newer rows to return current answers. Preparing that work during ingestion paid off in both query speed and cost.

That is why Snowflake can’t match ClickHouse Cloud for real-time analytics.


Share this post

  • Y Combinator icon
  • X icon
  • Bluesky icon
  • Facebook icon
  • LinkedIn icon

Subscribe to our newsletter

Stay informed on feature releases, product roadmap, support, and cloud offerings!

Recent posts

Amog Iska · Oct 19, 2026
Alex Soffronow Pagonidis · Oct 16, 2026

Follow us

XBlueskySlackGithubTelegramMeetupRSS