learn-data-engineering-with-phoebe / Builder session 8 of 10
Learn Data Engineering with Phoebe · Builder track · Session 8 of 10

Distributed processing

When data outgrows one machine, you split the work across a cluster. That is the promise of Spark and its kin - and it comes with a bill. This session teaches the map-shuffle-reduce mental model, the honest tradeoff (clusters are slow to start and expensive to coordinate), and why a single-node engine like DuckDB beats a cluster for most real datasets. You will feel it: 300,000 rows aggregated in milliseconds, on a laptop, in this tab.

🔴 Builder track Practitioners: DE · analysts · DS · PMs Runs in your browser · DuckDB 45 min
0-3 · Recap 3-20 · Distribute, tradeoff, Spark 20-42 · Build-along: single-node muscle 42-45 · Q&A
Part 0

Where the pipeline stands

Seven sessions in, Daybreak's pipeline extracts from source (b2-b3), captures change (b6), lands data in Parquet, and stores it partitioned for fast scans (b4, b7). The data is shaped and the files are laid out well. Now the question every engineer eventually asks: what if it does not fit on one machine? That is when people reach for a cluster - and, too often, reach for it far too early. This session gives you the model and the judgement.

Live - presented in session Self-study - read after class ▶ Live pipeline - editable & runnable Official sources covered
★ What you walk out with today A clear mental model of distributed processing (map, shuffle, reduce) and why the shuffle is the expensive part; the judgement to know when a single machine wins and when a cluster is worth its overhead; and a browser tab that crunches 300,000 rows in milliseconds - proof that most data is smaller than you think.
Part 1 · covers DLAI Storage & Queries M1, Fundamentals of DE

Why distribute, and the shuffle tax 7 min live

One machine has a fixed ceiling: so much memory, so much disk, so many cores. When a dataset exceeds that ceiling, you split it across many machines and let each chew on a slice. That is distributed processing, and almost every big-data engine follows the same three-move shape: map (each worker processes its slice), shuffle (workers exchange data so related rows meet), reduce (combine into the answer).

Single node - one machine does it all 1 machine all rows in one memory answer no network, no coordination overhead Cluster - split, exchange, combine worker 1 worker 2 worker 3 map: each worker scans its slice SHUFFLE - rows move across the network (the tax) reduce answer
🔍 Click to zoom - one machine versus a cluster; the copper shuffle band is where the cost lives
LiveMap, shuffle, reduce - and why shuffle hurts4 min

Map and reduce are cheap: each worker reads local data and does local math, fully in parallel. The shuffle is the expensive move. To group all of Daybreak's orders by channel, every worker's "web" rows have to end up on the same machine as every other worker's "web" rows - which means shipping data across the network between machines. Network is orders of magnitude slower than memory, so the shuffle dominates the clock.

  • Parallelism is free; coordination is not. Splitting work sounds like pure speedup, but the machines must agree on who has what, retry failures, and move data. That coordination is the hidden cost.
  • Shuffle = network I/O. Any operation that regroups rows (GROUP BY across partitions, a join on a non-partition key, a global sort) forces a shuffle. Minimising shuffles is most of cluster tuning.
  • The model outlives the tool. Spark, MapReduce, Flink, Trino all shuffle. Learn the shape once and every engine reads the same.
Real world

The join that melted a cluster. A team joined two large tables on a key neither was partitioned by. The engine shuffled both tables in full across 40 machines - hours of network traffic - to answer a query a single well-partitioned machine finished in minutes. The cluster was not slow; the shuffle was.

Part 2 · the honest tradeoff

Most data is small - reach for a cluster last 6 min live

A cluster carries huge fixed overhead: spinning up machines, coordinating them, moving data on every shuffle, paying for idle nodes. A single-node engine has none of that. Modern machines are large - a laptop has 16-64 GB of memory, a cloud box hundreds - and engines like DuckDB are built to stream data that exceeds memory straight off disk. The result surprises people: single-node engines crush datasets up to ~100 GB and beyond, often faster than a cluster, because they skip the coordination tax entirely.

-- one machine, 300k rows, full aggregate - watch the milliseconds
SELECT count(*)                                   AS rows,
       round(sum(quantity * unit_price), 2)       AS total_revenue,
       round(avg(quantity * unit_price), 2)       AS avg_line_value
FROM big_orders;
Self-studyPartitioning is what makes parallelism possible3 min read

Distributed engines and single-node engines share one trick from session b7: partitioning. Splitting data into independent chunks (by month, by region) is exactly what lets many workers, or many CPU cores, process slices at once without stepping on each other. A cluster partitions across machines; DuckDB partitions across the cores in one machine. Same idea, different blast radius.

  • Good partitions cut the shuffle. If data is already partitioned by the key you group or join on, related rows are co-located and no network exchange is needed. This is why b7's partitioned Parquet layout pays off here.
  • Too many tiny partitions hurt. Coordination cost per partition is real; thousands of 1 MB files is slower than a few well-sized ones. Right-sizing partitions is the craft.
  • Single-node still parallelises. DuckDB uses every core. You get parallelism without a cluster - the best of both for the common case.
Part 3 · when a cluster is right

Spark in concept, and when to reach for it 4 min live

Apache Spark is the default distributed engine. Its core ideas are worth knowing even if you rarely run it: an immutable dataset (RDD, or the friendlier DataFrame) split across the cluster, and lazy evaluation - transformations do not run when you write them; they build a plan, and only an action (write, collect, count) triggers the whole plan to execute. That lets Spark optimise the plan before moving a single byte.

Lazy evaluation: build a plan, then run it once read source filter rows group by key action: .write() / .collect() lazy - Spark only records these, nothing runs yet the action triggers the whole plan On a cluster this shuffles and computes across machines. On DuckDB here, one machine does the same work eagerly - same result, no coordination overhead.
🔍 Click to zoom - transformations are lazy; an action triggers the plan across the cluster
Self-studyThe same aggregate, in PySpark (read-only)3 min read

Here is Demo 2's channel aggregate written for Spark. It cannot run in a browser - Spark needs a JVM and a cluster - so read it for shape, not to execute. Notice the lazy chain and the single action (.show()) that fires it:

PySpark · runs on a cluster, not here df = spark.read.parquet("s3://daybreak/orders/") result = ( df.filter(df.status == "completed") .groupBy("channel") .agg((F.sum(df.quantity * df.unit_price)).alias("revenue")) ) result.show() # <- the action: only now does the plan run

Reach for Spark when the data genuinely exceeds a big single machine (multiple terabytes), when your organisation already runs a Spark shop, or when a workload must span many machines for reasons beyond size. Below those thresholds, a single-node engine is simpler, cheaper, and usually faster.

Where orchestration lives Running Spark jobs on a schedule, sizing the cluster, retrying failed stages, and monitoring them is learn-dataops, not this course. Here we build the processing logic; DataOps operates it.
Demo 1 of 2

Single-node muscle: three aggregates on 300k rows ★ 11 min · everyone builds

One machine, no cluster, 300,000 rows. You will run three aggregates - by channel, by month, and a window - and read the millisecond timer under each result. The lesson lands in the numbers: at this scale, spinning up a cluster would be slower than the laptop you are on.

Aggregate 1: revenue by channel - a simple GROUP BY, the bread and butter of analytics.

Aggregate 2: orders by month - a GROUP BY on a derived key, still one fast scan.

Aggregate 3: a window - running revenue month over month. This renders; note the total time.

-- 1) revenue by channel
SELECT channel, count(*) AS orders,
       round(sum(quantity * unit_price), 2) AS revenue
FROM big_orders
GROUP BY channel;

-- 2) orders by month
SELECT strftime(order_date, '%Y-%m') AS month, count(*) AS orders
FROM big_orders
GROUP BY month
ORDER BY month;

-- 3) a window: running monthly revenue (this result renders)
WITH monthly AS (
  SELECT strftime(order_date, '%Y-%m') AS month,
         sum(quantity * unit_price)    AS rev
  FROM big_orders
  GROUP BY month
)
SELECT month,
       round(rev, 2)                                      AS revenue,
       round(sum(rev) OVER (ORDER BY month), 2)           AS running_revenue
FROM monthly
ORDER BY month;
Real world

No cluster needed at this scale. 300,000 rows is bigger than the daily volume of many real businesses, and it finishes in a blink on one machine. Teams routinely provision Spark clusters for datasets a laptop would eat for breakfast - paying cloud bills and coordination latency for parallelism they never needed. Measure first; distribute only when the number forces you to.

Demo 2 of 2

Your turn: heavier work, still one machine ★ 11 min · build your own

Two hands-on queries and one thinking exercise. Each editor re-seeds the 300k-row table fresh. Write, run, read the timer - then decide whether any of this would justify a cluster.

LiveQ1 · A heavier aggregate: channel and month together3 min
SELECT channel,
       strftime(order_date, '%Y-%m')        AS month,
       count(*)                             AS orders,
       round(sum(quantity * unit_price), 2) AS revenue
FROM big_orders
GROUP BY channel, month
ORDER BY channel, month;
LiveQ2 · A window that would shuffle in Spark4 min
SELECT customer_id,
       channel,
       round(sum(quantity * unit_price), 2) AS spend,
       rank() OVER (PARTITION BY channel
                    ORDER BY sum(quantity * unit_price) DESC) AS rank_in_channel
FROM big_orders
GROUP BY customer_id, channel
ORDER BY channel, rank_in_channel
LIMIT 20;
Self-studyQ3 · The cluster decision4 min

No SQL - a judgement exercise. Before provisioning a cluster, weigh three things:

  • Data size: does it actually exceed a big single machine? A modern cloud box holds hundreds of GB of memory and streams far more off disk. If your data fits, stop here.
  • Existing infrastructure: does your team already run and know Spark? A cluster you have to build, secure, and learn from scratch is a project, not a query.
  • Cost: a cluster bills for idle nodes and coordination latency. A single-node run on ephemeral compute is often cheaper and simpler for the same answer.

The default should be single-node. Distribute only when a specific number - not a vague "big data" instinct - forces the move.

Homework

Try it yourself - this week ◐ 20-30 min total

Source material

Official sources covered

This session teaches the distributed-processing core of the DeepLearning.AI Data Engineering Professional Certificate (Joe Reis) and Reis & Housley's Fundamentals of Data Engineering, run on a live single-node engine. Certificates, cloud labs, and videos stay on the official platforms. This page covers:

DLAI Storage & Queries - M1: distributed query processingPart 1 · map-shuffle-reduce and why the shuffle dominates
Fundamentals of Data Engineering (Reis & Housley) - distributed computeParts 1-2 · the tradeoff and the single-node case
DLAI Storage & Queries - M3: query engines and SparkPart 3 · Spark model touched; live Spark runs on a cluster, not here
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · In distributed processing, what is the shuffle?

Map and reduce are local and cheap. The shuffle exchanges data between machines over the network to regroup rows, which is orders of magnitude slower than memory - the dominant cost of a cluster.

2 · When does a single-node engine like DuckDB beat a cluster?

Clusters carry heavy fixed overhead. For the common case - datasets that fit on one large machine - a single-node engine using all its cores finishes faster because it pays no coordination tax. Most data is small.

3 · When is Spark the right tool?

Reach for a cluster last, not first. Spark earns its overhead at genuine multi-terabyte scale or where a team already operates it. Below that, single-node is simpler, cheaper, and usually faster.

Builder session 8 cheat sheet · pin this

Why distributeWhen data exceeds one machine's memory and disk, split the work across a cluster of machines.
Map-shuffle-reduceMap: each worker scans its slice. Shuffle: rows move across the network. Reduce: combine to the answer.
Shuffle is the taxThe shuffle moves data between machines. Network is far slower than memory, so it dominates the clock.
Most data is smallSingle-node engines crush ~100 GB+ on one machine, often beating a cluster. Reach for a cluster last.
Partitioning enables parallelismSplitting into independent chunks lets many cores or machines work at once. Good partitions cut the shuffle.
Spark modelImmutable RDD/DataFrame, lazy transformations that build a plan, an action (write/collect) triggers it.
When to use a clusterGenuine multi-TB data, an existing Spark shop, or must-span-machines needs. Otherwise single-node.
Running projectDaybreak's aggregates run on one machine in ms. Next: b9, the seams where pipelines break.