Trino vs Presto vs Apache Spark: Lakehouse Query Engines Compared (2026)
Pick the wrong query engine for your lakehouse and you will feel it in one of two places: the latency dashboard your analysts stare at, or the cloud bill your finance team forwards you with a red circle around it. The trino vs presto vs spark decision is not a religious war about which engine is “best” — it is a question about what kind of work you are actually running. One engine was built to answer an ad-hoc SQL question against a data lake in two seconds. Another was built to survive a six-hour transformation across ten thousand partitions without dying. They share ancestry, they overlap in features, and in 2026 they increasingly read the same Apache Iceberg tables — yet their execution models are so different that choosing incorrectly can cost you an order of magnitude in either speed or spend.
This is a systems comparison, not a scoreboard. We will go down to how each engine moves bytes between workers, why one materializes intermediate results and the others try hard not to, and where each one falls over.
What this covers: the Presto-to-Trino fork history, MPP pipelined execution versus Spark’s stage-based DAG, fault tolerance, Iceberg and Delta support, concurrency and memory models, a weighted decision matrix, and clear “choose X when” guidance for 2026.
Context and Background
The story begins at Facebook in 2012. The company’s analysts were running interactive queries against a multi-petabyte Hive warehouse, and Hive-on-MapReduce was punishingly slow — minutes to tens of minutes for questions that should feel conversational. A small team built Presto: a distributed SQL engine that kept intermediate data in memory and streamed it between workers, deliberately trading MapReduce’s disk-checkpointed durability for interactive latency. Facebook open-sourced it in 2013, and it spread quickly to Netflix, Airbnb, Uber, and eventually the cloud vendors.
In late 2018 the three original creators — Martin Traverso, Dain Sundstrom, and David Phillips — left Facebook and forked the project as PrestoSQL, taking the momentum and most of the active committers with them. Facebook kept developing PrestoDB and, in 2019, moved its governance to the Linux Foundation under the Presto Foundation. In December 2020 PrestoSQL renamed itself Trino to end the trademark confusion. So today there are two living descendants: Trino (the original authors’ line) and PrestoDB (the Meta/Linux Foundation line). They are architecturally close cousins but have diverged in connectors, SQL surface, and — most consequentially — native execution.
Apache Spark comes from a different lineage entirely. Born at UC Berkeley’s AMPLab around 2009 and donated to the Apache Software Foundation, Spark generalized MapReduce into a resilient in-memory compute framework built on the Resilient Distributed Dataset (RDD). SQL was bolted on later as Spark SQL. Spark is a batch-and-everything engine — ETL, machine learning, graph, and streaming — where the SQL layer is one API among several. That single difference in origin explains most of what follows. For how the underlying table formats these engines read have themselves diverged, see our Apache Iceberg vs Paimon table formats comparison. The canonical reference for Trino’s design remains the Trino documentation.
Why does this ancestry matter for a 2026 buying decision? Because the design pressures that shaped each engine are permanent. Presto was born to make a warehouse feel interactive; every architectural choice — in-memory pipelining, a shared always-on worker pool, cost-based join reordering tuned for latency — serves that goal. Spark was born to make arbitrary distributed computation survivable and expressive; its choices — durable shuffle, lineage recomputation, a general RDD/DataFrame API — serve that. Neither team made a mistake. They optimized different objective functions, and no amount of feature-copying fully erases that. Trino has added fault tolerance; Spark has added adaptive optimization and native vectorization. But a Spark job will still pay stage-scheduling latency you cannot tune away, and a Trino query will still hold intermediates in memory in a way that a giant unbounded shuffle punishes. The 2026 versions are close enough to overlap heavily yet far enough apart that the decision still turns on workload shape.
Two Execution Models: MPP Pipelining vs the Stage DAG
The single most important thing to understand about the trino vs presto vs spark question is that Trino and Presto are Massively Parallel Processing (MPP) engines that pipeline data through memory, while Spark is a stage-based engine that checkpoints between shuffle boundaries. Everything downstream — latency, fault tolerance, concurrency, cost — flows from this one architectural fork.

Figure 1: Trino and Presto pipeline data through in-memory operators between a coordinator and workers with no intermediate materialization, whereas Spark breaks a query into stages separated by shuffle boundaries that write to disk.
Figure 1 contrasts the two dataflow shapes: on the left, a coordinator plans a query and streams tuples through long-lived worker pipelines; on the right, a driver decomposes the job into stages, and each shuffle boundary spills partitioned data to local disk before the next stage reads it back.
Trino and Presto: coordinator, workers, and pipelined operators
A Trino or Presto cluster has one coordinator and many workers. The coordinator parses SQL, builds a logical plan, applies cost-based optimization, and cuts the plan into stages connected by exchanges. Crucially, those stages run concurrently and continuously: as soon as a worker produces a page of rows, it hands it downstream over the network, and the consuming operator starts working on it immediately. There is no waiting for an upstream stage to “finish” and land its output on disk. This is classic MPP pipelining, and it is why a well-tuned Trino query against Iceberg can return in single-digit seconds.
The tables are read by connectors — pluggable modules that expose an external system as SQL. Trino ships dozens: Iceberg, Delta Lake, Hudi, Hive, PostgreSQL, MySQL, Kafka, Elasticsearch, MongoDB, and many more. Because a single query can join across connectors, Trino is a genuine federation engine: one SQL statement can join an Iceberg fact table on S3 to a dimension table in PostgreSQL without an ETL step. This federation reach is arguably Trino’s strongest differentiator against Spark, whose data-source connectors are real but fewer and less uniformly first-class.
The cost of pipelining is memory pressure and, historically, fragility. Because intermediate results live in worker memory rather than on durable storage, a single worker crash mid-query has classically meant the whole query fails and must be re-run from scratch. That is the defining weakness the fault-tolerant execution work set out to fix.
Spark: stages, shuffle, and lineage
Spark decomposes a job into a Directed Acyclic Graph (DAG) of stages. A stage is a run of narrow transformations (map, filter) that need no data movement; a wide transformation (join, group-by, repartition) forces a shuffle — a stage boundary where each task writes its output partitioned by key to local disk, and the next stage’s tasks fetch the partitions they need. Spark deliberately materializes shuffle output. That write-to-disk is what makes Spark fault-tolerant: if a task or an entire executor dies, Spark uses the RDD lineage graph to recompute only the lost partitions from the last durable shuffle files, not the whole job.
On top of RDDs, Spark SQL adds the Catalyst optimizer (rule- and cost-based query planning), the Tungsten execution engine (off-heap memory management, cache-aware binary layouts, and whole-stage code generation that fuses operators into tight JVM loops), and Adaptive Query Execution (AQE), which re-optimizes the plan at runtime using actual shuffle statistics — coalescing partitions, switching join strategies, and handling skew after the numbers are in rather than guessing up front. Commercial forks add vectorized native engines (Databricks Photon, and open equivalents like Apache Gluten with Velox) that push execution into C++ for a further multiplier. Spark 4.0 and the subsequent 4.1 release (2025) made ANSI SQL mode the default, added the VARIANT semi-structured type, string collation, and Spark Connect as a decoupled client-server protocol. For a related streaming-versus-batch trade-off, see our Flink vs Spark Streaming vs Kafka Streams comparison.
Query planning and the SQL surface
The optimizer is where the engines quietly diverge in ways that bite production. Trino’s cost-based optimizer relies on connector-supplied table statistics to reorder joins and choose broadcast versus partitioned distribution; if your Iceberg tables lack fresh column stats, Trino falls back to heuristics and can pick a catastrophic join order on a many-table star schema. Running ANALYZE (or letting Iceberg maintain stats) is not optional at scale. Trino also leans hard on predicate and projection pushdown into connectors — a WHERE on a partition column becomes partition pruning at the storage layer, so the engine never reads files it does not need. Getting pushdown to fire is often the single biggest tuning lever.
Spark’s Catalyst optimizer does the same class of work but with a decisive extra weapon: Adaptive Query Execution re-plans mid-flight. Where Trino commits to a plan at submission time and lives with it, Spark can look at the actual size of a shuffle after stage one and decide, at runtime, to switch a sort-merge join to a broadcast hash join, coalesce 2,000 tiny partitions into 50, or split a skewed partition. This runtime adaptivity is a genuine advantage on unpredictable data where up-front statistics lie — and it partly explains why Spark tolerates messy, poorly-profiled tables that would trip Trino’s static planner. The trade-off is that AQE’s re-planning adds the very stage barriers that cost Trino-style engines nothing.
Why the models produce opposite latency profiles
Pipelining wins on time-to-first-and-last-row for small-to-medium queries: no shuffle files to write, no stage barriers, no scheduler round-trips between stages. Stage-based execution wins on robustness and throughput for enormous jobs: materialized shuffle output means a dying node costs you a few recomputed partitions instead of a six-hour restart, and the disk-backed intermediate state lets Spark process datasets far larger than aggregate cluster memory. In short: Trino and Presto optimize for latency; Spark optimizes for completion.
Make it concrete. Imagine an analyst runs a filtered aggregation joining a 200-million-row Iceberg fact table to a small dimension. On Trino, the coordinator broadcasts the dimension, scans the fact table with partition and predicate pushdown so only relevant Parquet row groups are read, and streams partial aggregates straight to the output — no data touches durable storage on the way, and the result lands in a few seconds. Run the identical query on a cold Spark cluster and you pay executor JVM startup, a broadcast exchange, and — if AQE decides a shuffle is needed — a stage boundary that writes to local disk before the final aggregation reads it back. For this shape of query Trino simply has less machinery in the critical path. Now invert it: a nightly job rebuilds a 5-TB derived table with three large joins and a window function over a dataset that exceeds cluster RAM. Here Spark’s willingness to spill every operator to disk and recompute lost partitions from lineage is exactly what you want; the same job on stock Trino risks a memory kill two hours in unless you have configured spill and FTE carefully. Same two engines, opposite outcomes, one architectural cause.
Deeper Comparison: Fault Tolerance, Iceberg, Concurrency, and Cost
This is where the abstract execution difference becomes an operational decision. Below is a weighted decision matrix across the dimensions that actually move the needle, followed by the mechanism behind each row.

Figure 2: A decision-matrix scoring flow — weight each dimension by your workload, score the three engines, and sum to a recommendation rather than choosing on reputation.
Figure 2 shows the scoring flow: you assign each dimension a weight reflecting your workload, score each engine 1–5, multiply, and total. The weights below are illustrative for a mixed interactive-analytics shop; a heavy-ETL shop would up-weight fault tolerance and throughput and the ranking would shift toward Spark.
| Dimension (weight) | Trino | Presto (PrestoDB) | Apache Spark |
|---|---|---|---|
| Interactive latency (0.20) | 5 | 5 | 2 |
| Batch/ETL throughput (0.15) | 3 | 3 | 5 |
| Fault tolerance on long jobs (0.15) | 4 (FTE) | 3 | 5 |
| Iceberg support depth (0.12) | 5 | 4 | 4 |
| Delta / Hudi breadth (0.08) | 4 | 3 | 5 |
| Federation / connectors (0.10) | 5 | 4 | 3 |
| High concurrency (0.10) | 4 | 4 | 3 |
| ML / non-SQL workloads (0.05) | 1 | 1 | 5 |
| Native/vectorized execution (0.05) | 3 | 5 (Velox) | 4 (Photon-class) |
| Weighted total (illustrative) | ~4.0 | ~3.8 | ~3.7 |
The scores are the author’s engineering judgment for a mixed-analytics profile, not a published benchmark. Re-weight for your own workload — the totals converge, and the winner flips with the weights.
Fault tolerance: all-or-nothing vs retry-from-shuffle
Historically, Trino’s honest answer to “what happens when a worker dies mid-query” was: the query fails. For interactive dashboards that is acceptable — you re-run a two-second query. For a two-hour ETL job it is not. Project Tardigrade delivered Fault-Tolerant Execution (FTE) to Trino: with retry-policy=TASK, Trino checkpoints exchange data to an external spooling store (S3, HDFS, or local disk), so a failed task is retried from the last checkpoint instead of restarting the whole query. FTE also enables smarter adaptive scheduling and better resource isolation for large queries. It is a genuine capability — the Trino fault-tolerant execution docs describe both QUERY and TASK policies — but it is opt-in, adds spooling overhead, and does not make Trino a batch engine. Spark’s fault tolerance, by contrast, is intrinsic: lineage-based recomputation from durable shuffle files is the default behavior of every job, with no configuration and no separate exchange store.
Iceberg, Delta, and Hudi support
All three engines read Apache Iceberg in 2026, but with different depth. Trino’s Iceberg connector is exceptionally complete: hidden partitioning, partition evolution, time travel, MERGE/UPDATE/DELETE, metadata tables, OPTIMIZE for compaction, and snapshot management — and, notably, FTE now works with Iceberg reads and writes. PrestoDB has a solid Iceberg connector as well, increasingly wired through the native path. Spark is a first-class Iceberg writer — much of Iceberg’s own tooling and maintenance procedures (compaction, expiring snapshots, rewriting manifests) are Spark procedures, so many teams write and maintain Iceberg with Spark and query it interactively with Trino. For Delta Lake, Spark is the reference implementation and the deepest integration; Trino reads and writes Delta well but Spark owns the write-heavy Delta path. Hudi leans Spark-and-Flink for writes. The pragmatic 2026 pattern: Spark (or Flink) writes and compacts the tables; Trino serves the interactive reads.
Concurrency, memory, and spill
Trino and Presto are built for many concurrent users. A coordinator schedules hundreds of concurrent queries across shared long-lived worker processes, using resource groups to cap memory and CPU per tenant. Because everything is in memory, a query that exceeds its memory limit either spills to disk (Trino supports spilling for joins, aggregations, sorts, and window functions) or is killed. Spark’s memory model is executor-centric: each executor has a unified region split between execution and storage, and Spark spills aggressively and naturally because disk materialization is already its normal mode — which is exactly why Spark tolerates datasets far larger than RAM but pays a latency tax to do it. For high-concurrency BI serving, Trino’s shared-worker model is generally more efficient than spinning up Spark executors per query.
Dig one level deeper into the memory model and the difference sharpens. Trino tracks memory in three buckets — user memory (the query’s own data structures, like hash tables), system memory (buffers the engine needs to run), and a per-node reserved pool for the largest query. The coordinator enforces query.max-memory (cluster-wide) and query.max-memory-per-node; a query that would exceed these either spills eligible operators or is killed with a clear resource-exceeded error. This makes Trino’s failure predictable: you know which limit tripped and can tune it or the plan. Spark’s unified memory manager splits each executor’s heap fraction between execution and storage regions that can borrow from each other, and spills happen operator-by-operator as tasks exceed their share. Spark’s failure is softer — it degrades to disk and keeps going — but harder to reason about, because a job that spills heavily may finish successfully yet run 5× slower than a properly sized one, hiding the problem behind a green checkmark. Trino tells you loudly when you are out of memory; Spark quietly makes it your future self’s problem.
Presto’s native execution: Velox and Prestissimo
PrestoDB’s most significant 2026 development is Prestissimo (Presto C++), a drop-in C++ replacement for Java workers built on the Velox execution library. It is generally available and, per Meta’s reporting, delivers large speedups — roughly 3× on TPC-DS-style workloads versus Java workers — by replacing JVM operator execution with vectorized C++. The 2025 PrestoCon introduced the Presto Sidecar to let the coordinator interoperate cleanly with native workers. This is PrestoDB’s clearest technical differentiation from Trino today, though it comes with known behavioral differences from Java Presto that can require query adjustment. See the Presto C++ documentation for the current support surface.
The mechanism behind the 3× number is worth unpacking, because it recurs across the ecosystem. JVM operator execution processes one row at a time through virtual method calls, boxing values and thrashing the CPU cache. A vectorized engine like Velox instead operates on columnar batches — thousands of values of one column laid out contiguously — so a filter or arithmetic operation runs as a tight loop the compiler can auto-vectorize into SIMD instructions, with branch prediction and cache locality working in your favor. This is the same principle behind Spark’s Tungsten whole-stage codegen and behind Photon-class native engines. The lesson: in 2026 the JVM query engine is increasingly a coordinator and planner, while the hot execution path is migrating to C++ across all three lineages. Trino’s own vectorization efforts and PrestoDB’s Velox path are two roads to the same destination.
Cost: the dimension nobody weights until the bill arrives
Cost is where the execution-model difference becomes a line item. Trino’s shared, always-on worker pool means fixed cluster cost regardless of how many small queries run — cheap when concurrency is high and queries are short, wasteful when the cluster sits idle. Because it never materializes shuffle to durable object storage in the default path, it also avoids the S3 PUT/GET and storage costs that a heavy Spark shuffle can accrue. Spark’s cost profile is the opposite: elastic executors that scale up for a big job and release, ideal for bursty batch ETL billed by the job, but with per-job JVM startup and shuffle-write overhead that makes it expensive for thousands of tiny interactive queries. The rule of thumb: short-and-many favors Trino’s fixed pool; large-and-bursty favors Spark’s elastic executors. Enabling Trino FTE shifts its cost toward Spark’s shape, since spooling intermediate exchange data to S3 reintroduces the storage and request charges pipelining avoided. Model your query mix, not a single query, before you compare dollars.
Trade-offs, Gotchas, and What Goes Wrong
The most common failure with Trino is the out-of-memory query kill. Because pipelined MPP keeps intermediates in memory, a naive join between two huge unpartitioned tables, or a GROUP BY on a high-cardinality key without adequate spill configuration, will blow past query.max-memory and get killed. The fix is not “add RAM” — it is partition pruning, pushdown-friendly predicates, and broadcast-vs-partitioned join selection. Trino will not silently checkpoint its way out of a bad plan the way Spark does.

Figure 3: Common failure modes mapped to their mitigations — Trino memory kills, Spark shuffle skew and slow stages, and the small-files problem that punishes all three engines.
Figure 3 maps each engine’s characteristic failure to its mitigation. Spark’s signature pain is shuffle skew: one key with far more rows than the rest sends a giant partition to a single task, which straggles while the cluster idles. AQE’s skew handling splits such partitions automatically in Spark 3.x and later, but skew that survives AQE still needs salting or a broadcast join. Spark also suffers from too many small tasks and JVM garbage-collection pauses on under-provisioned executors, and its startup and stage-scheduling overhead makes it a poor fit for sub-second interactive queries — you feel the DAG scheduler tax on every job.
A failure mode that punishes all three engines is the small-files problem: streaming or micro-batch writers that produce thousands of tiny Parquet files per partition destroy scan performance because every file is a separate open, seek, and footer read. This is a table-maintenance problem, not an engine problem — the fix is regular compaction (OPTIMIZE in Trino, rewrite_data_files in Spark/Iceberg), and it is a major reason the “Spark writes and compacts, Trino reads” division of labor works so well. Finally, watch version and connector drift: Trino ships a new release roughly monthly (Trino 482 landed in June 2026) and periodically drops old behaviors, so pin versions and read release notes before upgrading a production cluster. For a purpose-built alternative when your workload is really high-concurrency OLAP rather than lakehouse federation, compare against our ClickHouse vs Doris vs StarRocks OLAP decision record.
Practical Recommendations
Start from the workload, not the brand. If your dominant job is interactive, ad-hoc SQL and BI serving over a data lake — many concurrent analysts, sub-10-second expectations, joins across heterogeneous sources — choose Trino. It is the reference lakehouse query engine in 2026, has the deepest Iceberg connector, and its federation reach means fewer copies of data. If you already run Meta-scale native execution or want C++ vectorized workers and are comfortable on the PrestoDB line, Presto with Prestissimo/Velox is the play. If your dominant job is large-scale ETL, machine learning, or long fault-tolerant transformations, choose Spark — nothing else combines batch durability, non-SQL APIs, and Delta/Iceberg write depth as well.
Most mature 2026 lakehouses run both: Spark (or Flink) for ingest, transformation, ML, and table maintenance; Trino for the interactive serving layer on top of shared Iceberg tables. That is not indecision — it is using each engine for what its execution model was designed to do.
On sizing: for the Trino serving tier, right-size worker memory to your concurrency target, not your single biggest query — hundreds of small queries sharing a pool behave very differently from one monster query, and resource groups let you protect interactive users from a rogue analyst. Enable spill on join, aggregation, and window operators so a large query degrades instead of dying. For the Spark side, tune spark.sql.shuffle.partitions down from the historical default when your data is small (over-partitioning creates the small-task problem) and rely on AQE to coalesce; keep executors large enough to avoid excessive GC but not so large that a single failure is expensive. Above all, treat table maintenance as a first-class scheduled job, not an afterthought — the compaction cadence you set on your Iceberg tables affects every query on every engine reading them, and it is the cheapest performance win available across all three.

Figure 4: A decision flow — route by workload shape (interactive vs batch), fault-tolerance need, and non-SQL requirements to the engine whose execution model fits.
Figure 4 gives a routing flow you can apply directly: branch on interactive-vs-batch, then on fault-tolerance and non-SQL needs, landing on Trino, Presto, or Spark.
Quick checklist:
- Interactive SQL + federation + Iceberg reads → Trino.
- Native C++ vectorized workers on the PrestoDB line → Presto + Prestissimo.
- Big ETL, ML, streaming, Delta writes, fault-tolerant long jobs → Spark.
- Both ingest and serving matter → Spark/Flink write and compact, Trino serves.
- Long Trino ETL jobs → enable Fault-Tolerant Execution (
retry-policy=TASK) with a spooling store. - Any engine → schedule regular table compaction to defeat the small-files problem.
Frequently Asked Questions
What is the difference between Trino and Presto?
Both descend from Facebook’s 2012 Presto project. In 2018–2020 the original creators forked it into PrestoSQL and renamed it Trino, while Facebook/Meta kept PrestoDB under the Linux Foundation. Trino generally has more connectors, a faster monthly release cadence, and a very complete Iceberg connector. PrestoDB’s headline differentiator is Prestissimo, its C++/Velox native execution engine. Architecturally they remain close MPP cousins; the practical choice usually comes down to connector needs, native-execution appetite, and which community and vendor ecosystem you want to depend on.
Is Trino faster than Spark?
For interactive, ad-hoc SQL, yes — usually by a wide margin. Trino’s pipelined MPP execution keeps intermediate data in memory and streams it between workers with no shuffle-to-disk barriers, so short-to-medium queries return in seconds. But “faster” is workload-dependent: for a multi-hour ETL job across a dataset larger than cluster memory, Spark’s stage-based, disk-checkpointed model is more robust and often finishes where Trino would hit memory limits or lose a worker. Trino optimizes latency; Spark optimizes reliable completion of huge jobs.
Which engine has the best Apache Iceberg support?
Trino has the most complete interactive Iceberg read/write connector — time travel, partition evolution, MERGE, metadata tables, OPTIMIZE, and fault-tolerant execution against Iceberg. Spark is the reference writer and maintenance engine: much of Iceberg’s own compaction and snapshot tooling ships as Spark procedures. In practice, many teams use Spark to write and maintain Iceberg tables and Trino to query them interactively — a division that plays to each engine’s strengths rather than forcing one engine to do everything.
Can Trino handle fault-tolerant long-running queries?
Yes, with Fault-Tolerant Execution (Project Tardigrade). Setting retry-policy=TASK and configuring an exchange spooling store (S3/HDFS/local) lets Trino checkpoint intermediate exchange data and retry failed tasks instead of failing the whole query. It makes Trino viable for ETL-style batch work and improves large-query resource isolation. It is opt-in and adds spooling overhead, so it does not turn Trino into Spark — but it removes the historical “one worker dies, the query dies” objection for long jobs.
Do I need to choose just one engine?
Usually not. The dominant 2026 lakehouse pattern runs multiple engines over shared open table formats: Spark or Flink handles ingestion, heavy transformation, ML, and table compaction; Trino serves the interactive analytics and BI layer on top of the same Iceberg or Delta tables. Because the storage format is the contract, engines interoperate without data duplication. Choosing “just one” only makes sense when your workload is genuinely one-shaped — pure interactive analytics (Trino) or pure batch/ML (Spark).
What is Prestissimo and why does it matter?
Prestissimo (Presto C++) is a drop-in C++ replacement for PrestoDB’s Java workers, built on the Velox vectorized execution library. It is generally available in 2026 and reportedly delivers roughly 3× speedups on analytics workloads by moving operator execution out of the JVM into vectorized C++. It matters because it is PrestoDB’s clearest technical edge over Trino today. The trade-off is a set of known behavioral differences from Java Presto that can require query adjustments, so it needs validation before a wholesale migration.
Further Reading
- Apache Iceberg vs Paimon: lakehouse table formats compared (2026) — the storage layer these engines all read.
- Flink vs Spark Streaming vs Kafka Streams (2026) — the streaming counterpart to this batch-vs-interactive split.
- ClickHouse vs Doris vs StarRocks OLAP decision record (2026) — when a dedicated OLAP engine beats lakehouse federation.
- Trino documentation and Trino Fault-Tolerant Execution — primary sources.
- Apache Spark 4.0.0 release notes and Presto C++ docs — primary sources.
By Riju — about
