Sitemap
Manoj Kumar

Manoj Kumar

Data Enthusiast based in London(UK). Experience as a Back end developement and worked on various projects in Data Engineering, Cloud, JAVA, Data Integration

One SQL Query. Three different Data Sources. Zero ETL.

13 min readSep 7, 2026

--

A Hands-On Trino Demo with PostgreSQL, MongoDB, and Parquet

“What if you could join a relational database, a document store, and Parquet files sitting on object storage — in a single SQL statement — without moving a single byte?”

That’s not a thought experiment. That’s Trino, and in this post I’ll show you exactly how it works .

Press enter or click to view image in full size
One SQL Query. Three Databases. Trino Federated Query in Action.

The Problem: Your Data Is Everywhere

Modern data stacks are fragmented by design. A typical setup looks like this:

  • Operational data in an RDBMS (in this use case — PostgreSQL) — customers, orders, accounts
  • Event/behavioral data in a document store (here — MongoDB) — clickstreams, user events
  • Historical/analytical data in S3 — Parquet files, data lake tables

And every team wants something different from this scattered data:

  • Your analytics team wants to build BI dashboards and KPIs by joining data across all these sources.
  • Your data scientists need curated, aggregated datasets to unlock insights that only emerge when combining sources.
  • Your AI/ML team wants to train models on a data mart built from all of it.

The traditional answer? ETL.
Extract everything. Transform it. Load it into a warehouse.

Wait for pipelines to run. Pay for duplicate storage. Deal with data freshness lag. Maintain and monitor every pipeline — and when a downstream consumer reports bad numbers, trace the issue back through each source system one by one.

Trino skips all of that.
Query every source directly, in SQL — no movement, no duplication, no pipeline to babysit.

Press enter or click to view image in full size
Left: The fragmented, pipeline-heavy ETL approach. Right: Trino’s clean federation model.

What is Trino?

Trino (formerly PrestoSQL) is an open-source distributed SQL query engine originally developed at Meta to run queries across multiple data sources. The key insight:- Instead of moving data to a query engine, bring the query engine to the data.

How it works:

  1. You write a SQL query referencing tables across multiple “catalogs” (data sources)
  2. Trino’s Coordinator parses the query, builds an optimized distributed execution plan
  3. Workers execute plan fragments in parallel — each fragment talking to its native data source
  4. Results are streamed back, joined, and aggregated in memory
  5. You get a single result set — no data was moved or duplicated

Trino supports 20+ connectors out of the box: PostgreSQL, MySQL, MongoDB, Kafka, Delta Lake, Iceberg, Hive/Parquet, Cassandra, Elasticsearch, BigQuery, and more.

The Demo: A Real-World Federation Scenario

Let me walk you through a practical use case: building a Customer 360 view from three heterogeneous systems.

The Data

| Source              | Technology           | Tables                | Data                                   |
|---------------------|--------------------- |-----------------------|----------------------------------------|
| Customer profiles | **PostgreSQL** | `customers`, `orders` | 5,000 customers, 200,000 orders |
| Behavioral events | **MongoDB** | `events` | 20,000 clickstream documents |
| Transaction history | **Parquet on MinIO** | `transactions` | 70,000 rows across 14 daily partitions |

The business question: “For US customers who made a purchase event in the last two weeks, what is their total settled transaction spend?”

This requires joining all three sources. With ETL, you’d need three separate pipelines, a warehouse table, a scheduled refresh, and days of engineering.

With Trino: one SQL query.

The Architecture

Press enter or click to view image in full size
The Trino federation architecture: a Coordinator, one or more Workers, and three connectors to three completely different data stores.

The architecture is beautifully simple:

  • Coordinator (:8080) — receives your SQL, plans the execution, manages resource groups
  • Worker — executes the actual data scanning and in-memory joins
  • Connectors — pluggable adapters, one per data source

Each connector speaks the native protocol of its database: JDBC for PostgreSQL, the MongoDB wire protocol for MongoDB, and the Parquet/S3 API for the data lake.

Running It Locally

The entire stack runs on Docker Compose. You need Docker Desktop with 8GB RAM allocated(Depends upon how may worker and data volumn).

# Start the full stack + seed all data (~2-3 min on first run)
make start

# You can see below output once as part of above command.
# Refer to Make file where make start definition is given.
podman-compose up -d --build
43064e70a75c153a0ea5abed66b08e2981b7b43088bd59fb4b9f1a20ae4b62b0
039796be5c9ac1457093d604aac6e19e7ab5af9a31875bcd7a98b4881389876d
8f08aee614800a237906bd48114d733e5ac5bfac4ccdf731f141b0e880d7a253
c05eced0bdb41ea9b95a656472a6aa4d50cad0d8a2e33d14eb1c53fd6204f2ae
00d6bb5af855c13034661c8ec74c8deeeb0aeb0c8acba831282bf866b7fb0b1c
WARNING: image platform (linux/amd64) does not match the expected platform (linux/arm64)
e595cf9d155f45c7279ed6738f6c208d5bbfb27d1f0896ccf430f49df81e01fc
STEP 1/6: FROM apache/hive:4.0.0
STEP 1/5: FROM python:3.12-slim
STEP 2/5: RUN pip install --no-cache-dir "pyarrow==17.0.0" "boto3==1.35.36"
--> Using cache ee911dbc556358acf5ed440eeae49e619a46d7d4b0a63b23c4d757a719d7c0db
--> ee911dbc5563
STEP 3/5: WORKDIR /app
--> Using cache 4cc7750ff8fe37fe00a9354fe04da406b2ac16ca6368fb19b8fcabb71be3964c
--> 4cc7750ff8fe
STEP 4/5: COPY generate_and_upload.py .
--> Using cache 9fa58e6cdbfd8f99ea382790ef74297277162c3271d42900cda8cccd681cb133
--> 9fa58e6cdbfd
STEP 5/5: ENTRYPOINT ["python", "generate_and_upload.py"]
--> Using cache 71ecde15f6485ab14cd6159a454f436448e65244a65d05b17b5e1e5292770e96
COMMIT localtrino_dataseed
--> 71ecde15f648
Successfully tagged localhost/localtrino_dataseed:latest
71ecde15f6485ab14cd6159a454f436448e65244a65d05b17b5e1e5292770e96
STEP 2/6: USER root
--> Using cache 0c5cfe7df89e261ced389a25414b7b64e7f20027494ca34db8a7748136a5ccc2
--> 0c5cfe7df89e
STEP 3/6: RUN cp /opt/hadoop/share/hadoop/tools/lib/hadoop-aws-*.jar /opt/hive/lib/ && cp /opt/hadoop/share/hadoop/tools/lib/aws-java-sdk-bundle-*.jar /opt/hive/lib/
--> Using cache b688b02413c516f71a59f95f0d23acc1a52fcd44b2470b534d6e20efd7a24d3e
--> b688b02413c5
STEP 4/6: ADD https://repo.maven.apache.org/maven2/org/postgresql/postgresql/42.7.4/postgresql-42.7.4.jar /opt/hive/lib/postgresql-42.7.4.jar
--> Using cache 4b46d16d81f84aa8cfa31f12f0eb670c87fd3051fff6597946a1dd87d3f42dbc
--> 4b46d16d81f8
STEP 5/6: RUN chmod 0644 /opt/hive/lib/postgresql-42.7.4.jar
--> Using cache 9aa2d867875a314459cdfd8f8e80e9a1a39bb4c971802b11806847001fa630f5
--> 9aa2d867875a
STEP 6/6: COPY core-site.xml /opt/hadoop/etc/hadoop/core-site.xml
--> Using cache e595cf9d155f45c7279ed6738f6c208d5bbfb27d1f0896ccf430f49df81e01fc
COMMIT localtrino/metastore:4.0.0
--> e595cf9d155f
Successfully tagged localhost/localtrino/metastore:4.0.0
e595cf9d155f45c7279ed6738f6c208d5bbfb27d1f0896ccf430f49df81e01fc
0f113d7c007991d8afc9e0a1c660daaba646ab6b68b48747b6541c510037808d
45a293bcbd7b62706fc35380c37d0023d9c19583d604e5e43413b72a394b71f9
b8bdcac6bd5dfd5c8c7d5e8c9d84aef35ceb6a673eb84fcf5bc502b00cf1fe9c
8d303216fe41d485ee88beaf91ef6170781dd1e9fffff812e3ae419942edb55e
e398677b045a66598aec70b980bd1d2ef6794ab393018dd8691e922ec86184b2
2ac2170dd1f538a9bac6f72f80cdd5d86be6eb0933a256562497cd05d1a83021
82ed28753d2adb9ed65dea3d161f30c34398fae4f34436619cf1d1b68a913521
27a44e3ea9edadd7f6921cc7437a00091350aaf4eafe4242b6007a5428495a81
0141b489344f148071f763a659de2f1e669c955f6e56ebbbad747a118558f7bf
lt-postgres
lt-mongodb
lt-minio
lt-metastore-db
lt-metastore
lt-dataseed
lt-trino-coordinator
lt-trino-worker
Stack starting. Give it ~1-2 min, then: make bootstrap
Trino UI -> http://localhost:8080 (any username, no password)
MinIO UI -> http://localhost:9001 (minioadmin / minioadmin)
./scripts/bootstrap.sh
========================================================
Customer 360 Demo — Bootstrap
Seeding the lake catalog + registering tables in Trino
========================================================

▶ Step 1/3: Generating transaction history → MinIO
14 daily Parquet partitions × ~5,000 rows/day = ~70,000 transactions
Path: s3://lake/warehouse/transactions/dt=YYYY-MM-DD/transactions.parquet
8f08aee614800a237906bd48114d733e5ac5bfac4ccdf731f141b0e880d7a253
Seeding lake.raw.transactions: 14 partitions × 5000 rows/day = 70,000 transactions total
Destination: s3://lake/warehouse/transactions/dt=YYYY-MM-DD/transactions.parquet
bucket 'lake' already exists
✓ uploaded warehouse/transactions/dt=2024-01-01/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-02/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-03/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-04/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-05/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-06/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-07/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-08/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-09/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-10/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-11/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-12/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-13/transactions.parquet (5,000 rows)
✓ uploaded warehouse/transactions/dt=2024-01-14/transactions.parquet (5,000 rows)

Done. 70,000 transactions across 14 partitions uploaded to MinIO.
Run sql/00_bootstrap_lake.sql to register lake.raw.transactions in Trino.
✅ Parquet transaction history uploaded to MinIO.

▶ Step 2/3: Waiting for Trino coordinator + all 3 connectors to be ready ...
(postgresql connector → Postgres :5432)
(mongodb connector → MongoDB :27017)
(hive/lake connector → MinIO :9000 via Hive Metastore :9083)
⏳ Waiting for Trino coordinator at http://localhost:8080/v1/info (timeout: 180s) ...
Trino must load postgresql + mongodb + hive/lake catalogs before
any federated query can run. This can take 60–120 s on first boot.
... still initialising (3s elapsed) [starting=not_up
not_up]
... still initialising (6s elapsed) [starting=True]
... still initialising (9s elapsed) [starting=True]
... still initialising (12s elapsed) [starting=True]
✅ Trino is ready (12s).

⏳ Waiting for Hive Metastore at localhost:9083 ...
(this is often the slowest service, especially on Apple Silicon)
✅ Hive Metastore is ready (0s after Trino).
✅ Trino is ready — all catalogs loaded.

▶ Step 3/3: Registering lake.raw.transactions in the Hive Metastore ...
Creating schema lake.raw → s3a://lake/warehouse
Registering external table lake.raw.transactions (partitioned by dt)
Syncing 14 dt= partitions so Trino can prune on date filters
Sep 07, 2026 11:02:18 AM org.jline.utils.Log

CREATE SCHEMA
DROP TABLE
CREATE TABLE
CALL
"70000"
"2024-01-01","5000"
"2024-01-02","5000"
"2024-01-03","5000"
"2024-01-04","5000"
"2024-01-05","5000"
"2024-01-06","5000"
"2024-01-07","5000"
"2024-01-08","5000"
"2024-01-09","5000"
"2024-01-10","5000"
"2024-01-11","5000"
"2024-01-12","5000"
"2024-01-13","5000"
"2024-01-14","5000"
✅ lake.raw.transactions registered — 14 partitions visible to Trino.

========================================================
Bootstrap complete! All 3 data sources are ready:

PostgreSQL → postgresql.public.customers (5,000 rows)
postgresql.public.orders (200,000 rows)
MongoDB → mongodb.demo.events (20,000 docs)
Lake/MinIO → lake.raw.transactions (~70,000 rows, 14 partitions)

Trino UI : http://localhost:8080 (query list, live plans, workers)
MinIO UI : http://localhost:9001 (minioadmin / minioadmin)

Run 'make demo' to walk through the 6 SQL demo sections.
========================================================

That single make start command:

  1. Builds and starts 8 Docker containers (Trino coordinator, Trino worker, PostgreSQL, MongoDB, MinIO, Hive Metastore, Metastore DB, and a data seeder)
  2. Generates synthetic data and uploads 14 Parquet partitions to MinIO
  3. Registers the Parquet files as an external Hive table in the Metastore
  4. Waits for Trino to be fully ready
Press enter or click to view image in full size
The 8-container Docker Compose stack — every service Trino needs, running locally.

Below are the Docker Images you can see in Podman/Docker desktop:

Press enter or click to view image in full size
All 8-docker images appeared post make start

Local trino: 8-container docker compose track with their high level of tasks.
1. lt-postgres : Source 1: Postgres — the "system of record" (customers + orders)

2. lt-mongodb : Source 2: MongoDB — event documents (JSON blobs / clickstream)

3. lt-minio : Source 3a: MinIO — S3-compatible object storage (Parquet files)

4. lt-metastore-db : Metastore backing DB — a tiny Postgres that holds the Hive Metastore’s own tables (the table/partition catalog).

5. lt-metastore : Source 3b: Hive Metastore — the “table catalog” in front of MinIO.A connector is just a config file + a pushdown implementation.The Hive connector needs a metastore to know where the files are.

6. lt-dataseed : One-shot: generate partitioned Parquet and upload it to MinIO. Writes s3://lake/warehouse/transactions/dt=YYYY-MM-DD/*.parquet. Runs, uploads, exits 0. Re-run any time with ‘make seed-lake’

7. lt-trino-coordinator : Trino COORDINATOR (Orchestrator). Plans queries, owns the UI (:8080), applies resource groups. Does NOT scan data itself (node-scheduler.include-coordinator=false).

8. lt-trino-worker : Trino WORKER: does the actual scanning/joining. Add more of these to scale out. Shares the exact same catalog files as the coordinator.

Once up, open the Trino Web UI at http://localhost:8080 — you’ll see the live query list, active workers, and memory usage.

Press enter or click to view image in full size
Trino Web UI

Step 1: Prove Connectivity

Before running heavy lifting query, let’s verify each connector is working independently:

-- Show all configured catalogs
SHOW CATALOGS;
-- ######### SHOW CATALOGS Output:Starts ######### --
Catalog
------------
lake
mongodb
postgresql
system
(4 rows)

Query 20260907_122614_00002_gm2zu, FINISHED, 1 node
Splits: 7 total, 7 done (100.00%)
0.61 [0 rows, 0B] [0 rows/s, 0B/s]
-- ######### SHOW CATALOGS Output:Ends ######### --

-- Query Postgres directly
SELECT customer_id, full_name, country, tier
FROM postgresql.public.customers
LIMIT 5;

-- Query MongoDB directly
SELECT customer_id, event_type, event_ts
FROM mongodb.demo.events
LIMIT 5;

-- Query the Parquet data lake directly
SELECT customer_id, amount, status, dt
FROM lake.raw.transactions
LIMIT 5;

Notice the naming convention: catalog.schema.table. The catalog name (postgresql, mongodb, lake) maps to a connector configuration file. Within a single session, you can freely reference any table from any catalog.

Step 2: The Money Shot — The Federated Join

Here it is. The query that crosses all three systems in a single statement:

SELECT
c.customer_id,
c.full_name,
c.country,
c.tier,
count(DISTINCT e.event_ts) AS purchase_events,
count(t.transaction_id) AS transactions,
round(sum(t.amount), 2) AS total_spend
FROM postgresql.public.customers AS c -- Postgres
JOIN mongodb.demo.events AS e -- MongoDB
ON e.customer_id = c.customer_id
AND e.event_type = 'purchase'
JOIN lake.raw.transactions AS t -- Parquet in MinIO
ON t.customer_id = c.customer_id
AND t.status = 'settled'
WHERE c.country = 'US'
GROUP BY c.customer_id, c.full_name, c.country, c.tier
ORDER BY total_spend DESC
LIMIT 20;

What’s happening under the hood:

  1. Trino sends a filtered scan to PostgreSQL — WHERE country = 'US' is pushed down
  2. In parallel, Trino scans MongoDB filtering event_type = 'purchase'
  3. In parallel, Trino scans Parquet files in MinIO filtering status = 'settled'
  4. All three result sets are streamed to the Workers, where they’re hash-joined in memory
  5. Results are aggregated and returned — no data was written anywhere

Run it yourself:

make demo         # Interactive walkthrough with narration
# OR
make sql F=02_federated_join.sql # Run this specific script

Step 3: Pushdown — How Trino Stays Fast

Federation sounds like it would be slow — wouldn’t it just scan entire tables? No, because of pushdown.

Get Manoj Kumar’s stories in your inbox

Join Medium for free to get updates from this writer.

Trino aggressively pushes predicates, projections, and aggregations into each native data source.

Press enter or click to view image in full size
Predicate pushdown: Trino sends the WHERE clause into Postgres instead of scanning all 200,000 rows.

Predicate Pushdown (fast case)

EXPLAIN ANALYZE
SELECT count(*)
FROM postgresql.public.orders
WHERE regexp_like(status, 'refund'); -- Trino-specific function!

Now Trino can’t translate regexp_like into native Postgres SQL. It pulls all 200,000 rows and filters them in Trino's memory. The TableScan node's Input: field will show the full row count — a dead giveaway.

The lesson: Stick to standard SQL predicates for best performance. Use EXPLAIN religiously.

Dynamic Filtering (cross-source magic)

EXPLAIN ANALYZE
SELECT c.country, count(*) AS n
FROM postgresql.public.customers c
JOIN mongodb.demo.events e
ON e.customer_id = c.customer_id
WHERE e.event_type = 'purchase'
GROUP BY c.country
ORDER BY n DESC;

Here, the filter (event_type = 'purchase') lives in MongoDB, but we're also scanning Postgres. Trino uses Dynamic Filtering: the Mongo scan runs first, builds a runtime bloom filter of matching customer_id values, and pushes that filter into the Postgres scan. Look for dynamicFilter in the query plan.

Step 4: Resource Groups — Protecting Your Sources

Running ad-hoc analytics on production databases is dangerous. Trino’s Resource Groups let you impose concurrency limits, queue depths, and memory caps per user group or query type.

The demo ships with this configuration:

{
"rootGroups": [{
"name": "global",
"softMemoryLimit": "80%",
"maxQueued": 100,
"hardConcurrencyLimit": 10,
"subGroups": [
{
"name": "analysts",
"softMemoryLimit": "20%",
"hardConcurrencyLimit": 2,
"schedulingPolicy": "fair"
},
{
"name": "protected-postgres",
"hardConcurrencyLimit": 1,
"schedulingPolicy": "fifo"
},
{
"name": "etl",
"hardConcurrencyLimit": 4
}
]
}]
}

Try it yourself — fire concurrent queries and watch them queue:

# Terminal 1: Fire 8 concurrent federated queries
make demo-throttle

# Terminal 2: Watch the queue
make queries

You’ll see queries routed to different resource groups and queued when limits are hit — protecting downstream databases from runaway queries.

Step 5: Partition Pruning

The transactions Parquet table is partitioned by dt (date). Fourteen partitions, one Parquet file each.

-- Fast: Trino reads ONLY one partition file
SELECT sum(amount)
FROM lake.raw.transactions
WHERE dt = '2024-01-14';

-- Slow: Trino reads all 14 partitions
SELECT sum(amount)
FROM lake.raw.transactions;

Run EXPLAIN ANALYZE on both and compare the Input: bytes scanned. Partition pruning is essential for lake-scale performance — and Trino handles it automatically when your predicate matches a partition column.

Step 6: CTAS — Federation as Ingestion

Here is the pattern that often blows people’s minds: use Trino not just to query, but to materialize.

CREATE TABLE lake.raw.customer_360
WITH (format = 'PARQUET')
AS
SELECT
c.customer_id,
c.full_name,
c.country,
c.tier,
count(DISTINCT e.event_ts) AS purchase_events,
count(t.transaction_id) AS transactions,
round(sum(t.amount), 2) AS total_spend
FROM postgresql.public.customers c
JOIN mongodb.demo.events e
ON e.customer_id = c.customer_id
AND e.event_type = 'purchase'
JOIN lake.raw.transactions t
ON t.customer_id = c.customer_id
AND t.status = 'settled'
GROUP BY c.customer_id, c.full_name, c.country, c.tier;

This CREATE TABLE AS SELECT (CTAS) runs the federated join once and writes the result as a managed Parquet table directly into MinIO. From this point forward, your BI dashboards query lake.raw.customer_360 — a fast, pre-joined Parquet file — without touching PostgreSQL or MongoDB again.

Press enter or click to view image in full size
The Customer 360 materialization flow: three live sources federated by Trino, written once to the lake as Parquet.

This is federation as an ingestion tool. Your ETL pipeline just became a SQL statement.

The Full Demo Walkthrough

make demo

This runs all 6 demo sections interactively, with narration pauses between each step. Or run them individually:

| Command                               | What It Does                   |
|-------------------------------------- |--------------------------------|
| `make sql F=01_connectivity.sql` | Prove all 3 connectors work |
| `make sql F=02_federated_join.sql` | The 3-way cross-source JOIN |
| `make sql F=03_pushdown.sql` | Pushdown analysis with EXPLAIN |
| `make sql F=04_protect_sources.sql` | Resource group monitoring |
| `make sql F=05_partition_pruning.sql` | Partition pruning comparison |
| `make sql F=06_ctas_materialize.sql` | Materialize to Parquet |

When Should You Use Trino?

Great for Trino:

  • Ad-hoc federated queries across systems you don’t want to centralize
  • Data exploration and discovery before committing to a pipeline
  • Replacing point-in-time ETL jobs with on-demand federation
  • Building a lakehouse query layer over S3/GCS/Azure Blob
  • Cross-region data federation where copying data isn’t feasible

Trino is NOT a replacement for:

  • OLTP workloads (high-concurrency transactional reads/writes)
  • Streaming pipelines (use Flink, Spark Streaming, or Kafka)
  • Long-running batch jobs that need fault-tolerance and checkpointing (use Spark)
  • Scenarios where network latency between systems is too high for interactive queries

Key Takeaways

  1. Trino federates, not replicates. Data stays in its native home. No staging tables, no copies, no lag.
  2. Pushdown is critical. When writing federated queries, think about what predicates Trino can push into each connector. Use EXPLAIN to verify.
  3. Partition your lake tables. Partition pruning on date columns can reduce bytes scanned by 90%+ on large datasets.
  4. Resource groups are essential in production. Without concurrency limits, a single analyst can accidentally bring down a production Postgres database.
  5. CTAS turns federation into ingestion. When a federated query gets heavy or needs to serve dashboards, materialize it to Parquet with CREATE TABLE AS SELECT.

Trino in Production

The demo runs on a single coordinator + single worker. In production, you’d have:

  • Multiple workers (auto-scaling on Kubernetes via the Trino Operator)
  • External Metastore (AWS Glue, or a dedicated Hive Metastore cluster)
  • Authentication (LDAP, OAuth2, or certificate-based)
  • TLS everywhere (coordinator-to-worker, client-to-coordinator)
  • Monitoring (Trino JMX metrics to Prometheus to Grafana)

The query language and concepts you learned here transfer directly to a production Trino cluster on AWS, GCP, or on-prem.

Get Started


make start # Everything up and seeded in ~3 minutes
make demo # Interactive walkthrough

# Explore further:
make shell # interactive Trino SQL shell (type your own queries)
make demo-throttle # fire 6 concurrent queries, watch resource groups
make psql # Postgres shell — inspect customers / orders
make mongosh # Mongo shell — inspect demo.events
make minio # MinIO console — browse Parquet files
make clean # stop all containers and delete volumes

Further Reading

If this post helped you, hit the clap button and follow for more data engineering deep-dives. Got questions about running Trino in production? Drop them in the comments below.

#Data Engineering, #Trino, #SQL query Engine, #Docker, #PostgreSQL, #MongoDB, #Parquet, #Data Lake, #Federated Query, #Open Source

--

--

Written by Manoj Kumar

Data Enthusiast based in London(UK). Experience as a Back end developement and worked on various projects in Data Engineering, Cloud, JAVA, Data Integration