FFastero

Connect any database. Ask in plain English.

Try free
Back to blog

Blog article

Trino vs DuckDB: Distributed vs Embedded Analytics (2026)

Trino queries data across dozens of sources without moving it. DuckDB processes analytical SQL faster than anything else on a single machine. This guide covers architecture, performance at different data scales, and when each engine fits.

Fastero Dev TeamFastero Dev Team
2026-08-29
TrinoDuckDBSQLanalyticsdata engineering
Trino vs DuckDB: Distributed vs Embedded Analytics (2026)

Trino is a distributed SQL query engine that federates queries across data wherever it lives — S3, Postgres, Kafka, Hive, Elasticsearch, and dozens more — without copying it into a warehouse first. DuckDB is an in-process OLAP engine that runs analytical SQL on a single machine at speeds that embarrass most clusters. They solve fundamentally different problems, and choosing between them is really a question of data topology.

Comparison Table

Dimension Trino DuckDB
Architecture Distributed coordinator + workers Single-process, in-memory/out-of-core
Deployment Cluster (3+ nodes typical) pip install duckdb or single binary
Data access 50+ connectors (S3, RDBMS, Kafka, Delta, Iceberg) Local files (Parquet, CSV, JSON), attached databases
Query model Federated — push predicates to sources Local — scan files or attached storage directly
Concurrency Designed for hundreds of concurrent queries Best for single-user or low-concurrency workloads
Scaling Horizontal — add workers Vertical — bigger machine
Performance (single query) Network-bound; fast on large distributed scans Extremely fast; vectorized columnar on local data
SQL dialect ANSI SQL, well-tested with complex joins/CTEs Rich SQL, window functions, arrays, nested types
Operational cost High — JVM cluster, coordinator HA, catalog config Near-zero — no server, no daemon, no config
Persistence Stateless query engine (reads from source) Optional persistent database files
Language Java C++
Cloud managed Starburst Galaxy, Amazon Athena (Trino-based) MotherDuck (cloud DuckDB)

How do Trino and DuckDB differ architecturally?

Trino runs as a cluster: one coordinator receives SQL, plans execution, and distributes query fragments across worker nodes. Each worker pulls data from the relevant connector — a Hive metastore partition, an S3 prefix, a PostgreSQL table — processes it locally, and streams partial results back. The coordinator merges results and returns them to the client. Data never lands in Trino itself; it is a pure compute layer that sits between your sources and your analysts.

This architecture means Trino scales horizontally. Need to scan more data faster? Add workers. Need to query a new source? Add a catalog config file. The coordinator handles cross-source query planning — you can JOIN a Postgres users table with a Delta Lake events table and a Kafka topic in one SQL statement. The cost-based optimizer decides which side of the join to broadcast, which to partition, and which predicates to push down to connectors.

Trino also separates compute from storage entirely. Workers are stateless — they can crash and restart without losing data. This makes autoscaling practical: spin up extra workers during business hours, scale down overnight. The tradeoff is that every query pays a coordination tax (plan distribution, result merging, heartbeats) that adds 50-200ms of baseline latency even on trivial queries.

DuckDB runs inside your process. import duckdb in Python and you have a full vectorized OLAP engine with zero network hops. It reads Parquet, CSV, and JSON files directly via column pruning and predicate pushdown. It processes data in batches of vectors — the same execution model that makes analytical databases fast — but compressed into a library you embed in your application or notebook.

DuckDB automatically parallelizes across all available cores on the machine. Its query planner is optimized for single-node execution: it can use hash joins, merge joins, and sort-merge joins without worrying about network shuffles or partition skew. The result is that a single DuckDB query on local data will almost always be faster than the same query on Trino, because there is literally no network in the path.

DuckDB scales vertically. A machine with 64 cores and 256GB of RAM will let DuckDB process hundreds of gigabytes in seconds. But there is a ceiling: one machine, one process, and no way to shard a single query across multiple nodes.

Fastero

Connect your database. Ask questions. Get dashboards.

Postgres, BigQuery, Snowflake, and 10+ sources — live-connected, AI-powered, no dashboard builder learning curve.

Try free →

Federated queries vs local processing — what is the real tradeoff?

Trino's federation is its defining feature. Most organizations have data spread across five to fifteen systems: a transactional Postgres, a data lake on S3, event streams in Kafka, a CRM export in Snowflake, logs in Elasticsearch. Trino queries across all of them without an ETL pipeline to centralize the data first. You define connectors, and analysts write SQL as if everything lived in one database.

The cost is network. Every federated query moves data from sources over the network to Trino workers, then between workers for shuffles and joins. A query that scans 50GB from S3 and joins it with 2GB from Postgres is bounded by network throughput, not CPU. Predicate pushdown helps — Trino pushes filters to connectors so only matching rows travel — but cross-source joins still require moving data between systems.

There is also a correctness consideration. Federated joins across systems with different consistency models can produce surprising results. A Postgres table gives you snapshot isolation; an S3 partition gives you eventual consistency; a Kafka topic gives you offset-based ordering. Trino does not coordinate transactions across sources — it reads each connector independently. For most analytical workloads this is fine, but it is worth knowing.

DuckDB has no federation layer. It reads files it can access directly: local Parquet, S3-hosted Parquet (via the httpfs extension), or attached Postgres/MySQL databases (via community extensions). These extensions are single-source scans, not federated query planning. You cannot join a Postgres table with an S3 file and expect DuckDB to push predicates to both — it pulls everything locally first, then joins in-process.

If your data lives in one place (a data lake, a set of exported files, a single database), DuckDB is dramatically faster because there is no network hop. If your data lives in ten places and you refuse to centralize it, Trino is the only engine that queries across all of them in a single SQL statement.

How do their SQL dialects compare?

Both engines speak SQL, but the dialects reflect their different origins.

Trino follows ANSI SQL closely. It supports standard joins (INNER, LEFT, RIGHT, FULL, CROSS, LATERAL), window functions, CTEs, subqueries, GROUPING SETS, CUBE, and ROLLUP. The type system is strict — implicit coercions are limited, and you will get type errors that Postgres or MySQL would silently coerce. This strictness catches bugs but requires more explicit casting in queries.

Trino also exposes connector-specific functions and tables. You can query Iceberg metadata tables ($snapshots, $manifests, $partitions) directly in SQL. Kafka connector tables expose message offsets and timestamps as queryable columns. This connector-aware SQL layer is unique to Trino — no other engine lets you inspect data source internals through standard SQL.

DuckDB extends ANSI SQL with features borrowed from Postgres and its own additions. It supports EXCLUDE, REPLACE, and RENAME clauses in SELECT (so you can write SELECT * EXCLUDE (internal_id) instead of listing every column). It has QUALIFY for filtering window function results without a subquery. List comprehensions, struct types, and nested data are first-class — you can query JSON and nested Parquet directly without flattening.

DuckDB also supports COPY ... TO for writing query results directly to Parquet, CSV, or JSON files. Combined with glob-based file reading, this makes DuckDB a self-contained ETL tool: read from files, transform with SQL, write to files. Trino can do similar things via INSERT INTO with a Hive/Iceberg connector, but the setup is heavier.

Here is the same analytical query in both dialects:

-- Trino: strict ANSI, explicit casting
SELECT
  date_trunc('month', CAST(event_time AS timestamp)),
  customer_segment,
  COUNT(*) AS events,
  APPROX_PERCENTILE(latency_ms, 0.95) AS p95
FROM lakehouse.events.page_views
WHERE event_time >= TIMESTAMP '2026-01-01'
GROUP BY 1, 2
ORDER BY 1;
 
-- DuckDB: same result, more ergonomic syntax
SELECT
  date_trunc('month', event_time),
  customer_segment,
  COUNT(*) AS events,
  quantile_cont(latency_ms, 0.95) AS p95
FROM 'events/page_views/*.parquet'
WHERE event_time >= '2026-01-01'
GROUP BY ALL
ORDER BY 1;

Both queries run fine. DuckDB's GROUP BY ALL avoids repeating the non-aggregated columns. Its implicit timestamp coercion avoids the explicit CAST. Trino's fully qualified lakehouse.events.page_views names the catalog, schema, and table — useful when the same table name exists in multiple sources.

For analysts who write SQL daily, DuckDB's ergonomic additions — EXCLUDE, QUALIFY, GROUP BY ALL, COLUMNS(regex) — save real time. For platform teams who need strict ANSI compliance and cross-source consistency, Trino's stricter dialect is the safer bet.

How do they perform at different data scales?

Performance depends heavily on the query pattern and where the data lives. A few general observations before the scale breakdown:

  • Large aggregation scans (COUNT, SUM, AVG over millions of rows with GROUP BY) favor DuckDB on local data because vectorized columnar execution without network overhead is hard to beat. Trino's distributed scan catches up only when the data is already sharded across workers.
  • Point lookups and selective filters that return small result sets are fast on both engines. Trino adds network latency; DuckDB does not. On truly selective queries the absolute difference is small (milliseconds vs. tens of milliseconds) but DuckDB is always faster for local data.
  • Multi-source joins are Trino's exclusive territory. DuckDB cannot execute a join where one side is in Postgres and the other is on S3 without pulling both locally first.
  • Complex nested queries (CTEs with multiple levels, window functions over large partitions) favor DuckDB for single-machine execution. Trino's distributed plan can introduce unnecessary shuffles on queries that do not naturally partition.

Under 100GB, single source: DuckDB wins outright. A modern laptop processes 100GB of Parquet in seconds to low minutes. Trino's cluster overhead — coordinator planning, worker scheduling, network serialization — adds latency that does not exist in DuckDB's in-process model. For ad-hoc analysis on exported data, DuckDB is 5-50x faster in wall-clock time depending on query complexity.

100GB-10TB, single source: DuckDB still works if you have a sufficiently large machine (or use MotherDuck for cloud-scale storage). Trino becomes competitive because its distributed workers parallelize the scan across nodes. The crossover depends on your hardware budget — one 256GB machine running DuckDB vs. a 10-node cluster scanning the same S3 bucket with Trino. If latency matters more than cost, DuckDB on a large instance often wins. If you already have the cluster, Trino keeps up.

10TB+, multiple sources: Trino's territory. At this scale, the data does not fit on one machine, and it probably lives across multiple systems. Trino's distributed execution and connector ecosystem are designed for exactly this: scan petabytes across a data lake and join with operational databases. DuckDB cannot participate here — there is no way to shard a query across multiple DuckDB instances.

Concurrent dashboard queries: Trino handles hundreds of concurrent queries from BI tools across a shared cluster. Resource groups let you prioritize interactive queries over batch jobs. DuckDB is optimized for single-user or small-batch workloads — run 50 concurrent analytical queries and they compete for the same CPU and memory on one machine. MotherDuck adds some concurrency headroom, but it is still not designed for the multi-tenant BI workload Trino handles natively.

How do their connector and extension ecosystems compare?

Trino's connector catalog is its moat. Out of the box, Trino ships connectors for Hive, Iceberg, Delta Lake, Hudi, PostgreSQL, MySQL, SQL Server, Oracle, MongoDB, Elasticsearch, Cassandra, Redis, Kafka, Kinesis, Google Sheets, and over 30 more. Each connector is maintained as part of the Trino project and follows a standard SPI (Service Provider Interface). Connector authors implement pushdown rules that tell the optimizer which predicates, projections, and aggregations can be executed at the source rather than on the Trino workers.

This matters for performance. A well-implemented connector means Trino only moves the rows and columns it needs. The Iceberg connector, for example, uses partition pruning and min/max column statistics to skip entire data files before reading a single byte. The Postgres connector pushes WHERE clauses and LIMIT down to the database.

DuckDB's extension system is younger but growing fast. Core extensions include httpfs (read from S3/GCS/Azure), postgres_scanner, mysql_scanner, sqlite_scanner, spatial, ICU (internationalization), json, and parquet. Community extensions add Excel, Google Sheets, and Delta Lake support. Extensions install at runtime — INSTALL httpfs; LOAD httpfs; — with no restart required.

The key difference: Trino connectors are designed for federated access to live systems. DuckDB extensions are designed for data ingestion into the local process. A Trino Kafka connector lets you query a live topic as a table. DuckDB has no equivalent — you would consume from Kafka separately and point DuckDB at the output files.

How do they handle modern table formats?

Both engines work with Apache Iceberg, Delta Lake, and Apache Hudi — the open table formats that are replacing traditional Hive-style partitioning on data lakes. But the integration depth differs.

Trino has first-class Iceberg and Delta Lake connectors maintained by the core project. The Iceberg connector supports time travel queries, schema evolution, partition evolution, and metadata tables that expose snapshots, manifests, and file-level statistics. You can query iceberg_table$snapshots to see version history, or use FOR VERSION AS OF to query a past state. Trino also supports Iceberg's row-level deletes (merge-on-read and copy-on-write), making it usable for updates on lakehouse data.

DuckDB reads Iceberg tables via the iceberg extension and Delta tables via the delta extension. Read support works well for analytical queries — DuckDB will use partition pruning and file-level statistics to skip unnecessary reads. Write support is more limited; DuckDB is primarily a read-and-analyze engine, not a table management layer. If you need to manage table versions, run compaction, or evolve schemas, those operations happen outside DuckDB (via Spark, Trino, or the table format's own tooling).

For lakehouse architectures, Trino is the query engine that participates as a full citizen — reading and writing Iceberg tables, managing snapshots, running analytics. DuckDB is the fast reader you point at a frozen snapshot for local analysis.

How does deployment complexity compare?

Trino requires a coordinator node, one or more worker nodes (three minimum for production), a catalog configuration per data source, a JVM tuned for large heap sizes, and either a discovery service or a static node list. Production deployments add a load balancer, coordinator HA (via multiple coordinators and a shared state store), and monitoring for worker health and query queuing.

Kubernetes deployments use the Trino Helm chart but still need catalog secrets, resource limits, and autoscaler tuning. Adding a new data source means writing a catalog properties file, restarting the coordinator (or using dynamic catalog management in newer versions), and testing that predicate pushdown works correctly for your specific query patterns against that source.

JVM tuning is a recurring theme. Trino workers need large heaps (16-64GB typical), and garbage collection pauses can cause query failures under memory pressure. Understanding -Xmx, G1GC tuning, and spill-to-disk settings is table stakes for running Trino in production.

DuckDB requires nothing. For Python users: pip install duckdb. For CLI users: download a single binary. There is no server process, no config file, no coordination layer. Your application starts, runs a query, and the engine shuts down with the process. Extensions (httpfs, spatial, ICU) install with a single INSTALL command inside a DuckDB session.

The operational gap is significant. Teams routinely spend weeks tuning Trino's memory settings, debugging OOM kills on workers, and troubleshooting connector issues with specific source versions. DuckDB's failure mode is simpler: you run out of RAM on the machine, and the fix is a bigger machine or a more selective query.

Managed services reduce the gap. Starburst Galaxy and Amazon Athena handle Trino cluster operations for you — but you still configure catalogs, manage access policies, and debug query plans. MotherDuck manages DuckDB in the cloud but is closer to a "works out of the box" experience because DuckDB's operational surface is smaller to begin with.

For teams without a dedicated platform or infrastructure engineer, the deployment complexity difference alone can be the deciding factor. Running Trino well requires someone who understands distributed systems. Running DuckDB requires someone who understands SQL.

When should you pick Trino?

Pick Trino when:

  • Your data lives across multiple systems (data lake + RDBMS + streaming) and you need cross-source joins without building ETL pipelines
  • You serve concurrent analytical queries to BI tools, dashboards, or multiple analysts simultaneously
  • Your data exceeds what one machine can hold — multi-terabyte to petabyte scale
  • You need to query data in place without copying it to a centralized warehouse
  • Your team already runs Kubernetes and has ops capacity for a JVM-based distributed system
  • You want a single SQL interface over your entire data estate for governance and access control

The canonical Trino use case: a platform team exposes a single SQL endpoint over a lakehouse (S3 + Iceberg) plus operational databases, serving Looker/Metabase dashboards and ad-hoc analyst queries through one query engine with unified access controls.

A common anti-pattern: using Trino when all your data is in one Postgres database. Trino's federation overhead adds no value if there is nothing to federate. Use DuckDB or query Postgres directly instead.

When should you pick DuckDB?

Pick DuckDB when:

  • Your data fits on one machine (up to a few hundred GB, more with MotherDuck)
  • You need maximum single-query speed for ad-hoc analysis, notebooks, or batch processing
  • You want zero infrastructure — no cluster, no server, no ops burden
  • You are building embedded analytics inside an application (DuckDB ships as a library)
  • Your workflow is analyst-local: explore exported data, prototype queries, build features for ML pipelines
  • You need to process files in a pipeline — DuckDB reads and writes Parquet/CSV natively, making it a fast ETL step between file-based stages

The canonical DuckDB use case: a data analyst exports last month's events to Parquet, opens a Jupyter notebook, and runs 30 exploratory queries against 50GB of data on their laptop — finishing the analysis in the time it would take to connect to the warehouse and wait for a query slot.

A common anti-pattern: using DuckDB as a production query engine for a multi-tenant SaaS application with concurrent users. DuckDB's single-process model means concurrent queries compete for the same resources. If you need to serve dashboards to 50 people simultaneously, Trino (or a proper OLAP database like ClickHouse) is the right tool.

The trend in 2026

DuckDB adoption has exploded. Two years ago it was a niche tool for data engineers who read Hacker News. Today it is the default local analytics engine — embedded in dbt, used inside Airflow tasks, powering local development for data teams who previously needed a cloud warehouse for everything.

Trino's adoption is steadier and enterprise-weighted. The Iceberg ecosystem is driving a wave of Trino deployments: companies building lakehouses on S3 + Iceberg use Trino (or Athena, which is Trino under the hood) as their primary query layer. Starburst's managed Trino service has made the ops burden less of a dealbreaker for mid-size teams.

The convergence point is table formats. As more data lands in Iceberg/Delta on object storage, both engines become complementary rather than competitive — Trino as the multi-source query fabric, DuckDB as the local turbo-reader for exported datasets. Teams that treat them as an either/or choice are leaving performance on the table.

Using Trino and DuckDB together

The best teams do not pick one — they use both for different stages of the analytical workflow.

Pattern 1 — Federation then deep-dive. Trino queries across your lakehouse, operational databases, and streaming systems. The analyst runs a federated query that joins three sources and filters down to 500K rows. They export the result to Parquet and open it in a local DuckDB session for 30 rounds of ad-hoc exploration — slicing, pivoting, testing hypotheses — without hitting the Trino cluster for each iteration.

Pattern 2 — DuckDB as a pipeline step. Data engineers use DuckDB inside Python scripts or Airflow tasks to perform fast local transforms: read Parquet from S3, run a complex aggregation, write the result back to S3. Trino then queries the output as part of a larger federated view. DuckDB handles the compute-intensive transform; Trino handles the cross-source query layer.

Pattern 3 — MotherDuck for sharing, Trino for governance. Analysts who need to share DuckDB results with teammates use MotherDuck as a cloud-hosted DuckDB. The platform team exposes Trino with access controls and audit logging for governed data access. Both engines coexist — Trino for production dashboards and governed queries, MotherDuck/DuckDB for analyst self-service on exported datasets.

Decision tree

Do you need to query data across multiple systems
in a single SQL statement?
 |
 +-- YES --> Do you have ops capacity for a JVM cluster?
 |            |
 |            +-- YES --> Trino (self-hosted)
 |            +-- NO  --> Managed Trino (Starburst Galaxy / Athena)
 |
 +-- NO  --> Does your data fit on one machine (<500GB)?
              |
              +-- YES --> DuckDB
              +-- NO  --> Do you need high concurrency?
                           |
                           +-- YES --> Trino or MotherDuck
                           +-- NO  --> DuckDB on a large instance

FAQ

Can DuckDB query remote databases like Trino does? DuckDB has community extensions for Postgres, MySQL, and SQLite that let you attach remote databases and query them. But this is single-source attachment, not federated planning — DuckDB pulls data locally before processing. It does not push predicates or joins to the remote source the way Trino does. For querying one remote database, it works fine. For joining across five sources with intelligent predicate pushdown, Trino is purpose-built.

Is Trino the same as Presto? Trino was originally called PrestoSQL. It forked from PrestoDB (the Facebook-managed project) in 2020 and rebranded to Trino in late 2020. Trino is the community-driven fork with faster development velocity, while PrestoDB remains under the Linux Foundation with Meta's backing. For a deeper comparison, see our Trino vs Presto vs Spark SQL post.

Can I use both Trino and DuckDB together? Yes, and this pattern is growing. Use Trino as the federation layer that queries your lakehouse and operational databases, export results to Parquet, and use DuckDB for fast local iteration on the extracted dataset. Trino handles the multi-source query; DuckDB handles the single-analyst deep-dive. Some teams also use DuckDB inside their data pipelines to do fast local transforms on files that Trino queries later.

How does MotherDuck change the DuckDB comparison? MotherDuck adds cloud hosting, sharing, and larger-than-local storage to DuckDB. It blurs the line — you get DuckDB's query speed with some of the accessibility of a cloud warehouse. It does not add Trino-style federation across arbitrary sources. If your core need is cross-source queries over data you cannot move, MotherDuck does not replace Trino. If your need is fast SQL over cloud-hosted data with team sharing, MotherDuck fills a gap DuckDB alone cannot.

What about Amazon Athena — is that just managed Trino? Athena v3 is built on Trino. It gives you serverless, per-query-priced access to Trino against S3 data (Parquet, ORC, Iceberg, Delta) without managing a cluster. You lose some connector breadth — Athena supports fewer catalogs than self-hosted Trino — but gain zero-ops scaling and pay-per-scan pricing. For teams whose data already lives in S3, Athena is the lowest-friction path to Trino-class query federation.

Which is cheaper to run? DuckDB costs you one machine (or nothing — it runs on your existing laptop). Trino costs a cluster of machines running 24/7, or per-query pricing via Athena/Starburst. For small-to-medium workloads on local data, DuckDB is dramatically cheaper. At warehouse scale with many concurrent users, Trino's cluster cost is offset by the ETL pipelines and data copies you no longer need to build and maintain. The real cost comparison is not "cluster vs. laptop" — it is "cluster vs. the data infrastructure you would build without federation."

Do either replace a data warehouse like Snowflake or BigQuery? Not directly. Trino is a query engine, not a storage engine — it queries data in place but does not manage storage, compaction, clustering, or materialized views the way a warehouse does. DuckDB is an embedded engine optimized for single-user analytics, not a multi-tenant serving layer. That said, Trino + Iceberg on S3 is increasingly used as a warehouse alternative (the "open lakehouse" pattern), and DuckDB + MotherDuck is replacing warehouse ad-hoc queries for individual analysts. Neither matches the fully managed operational experience of Snowflake, but both avoid vendor lock-in on data storage.

Related reading


Try Fastero free — connect multiple sources and query across them with AI — no Trino cluster, no DuckDB scripts. No credit card required.

Ready to try it yourself?

Connect your database, ask questions in plain English, and get live dashboards — in under 2 minutes. No credit card required.