Lesson F01.2Distributed data processing course / Foundations / Parallelism

Why adding more workers can make a job slower

Increasing workers from 16 to 64 made the nightly job 86 seconds slower.

20 min read · 11 sections · 7 predictions · Junior · verified @ python 3.13 · sim 0.1 · captured 2026-10-13
Before you start

Read Lesson F01.1 first: it defines record, job, worker, wall time, throughput, latency and floor. Nothing to install.

Terms are defined in this margin where they first appear.

01

The problem: more workers, slower execution

On 16 single-core workers the nightly validation job took 175 seconds. On 64 it took 261 seconds: 86 seconds slower, with the same code and input data. Why did adding more workers make the job slower?

02

Breaking down the job’s runtime

Let’s rebuild the job’s runtime on 16 and on 64 workers, one part at a time. Each part comes with the assumption it makes, so you can see exactly where the ideal stops.

Total runtime =Serial workT_s+next part?…
One process
no cluster, no overhead · off the scale →
1,242.4 s
16 workers
10.0 s
64 workers
10.0 s
0 s150 s300 s

Serial work

10 sPaid once

The coordinator spends 5 seconds reading the input manifest before processing begins, and another 5 seconds writing the final summary. This work cannot be divided among workers.

Assumes: it stays at 10 s however large the input grows. §3 shows what changes if it grows too.

At 16 workers and at 64: 10.0 s.

How Runtime Changes with Worker Count

WorkersSerial + FixedWorker OverheadParallel WorkTotal Runtime
150 s3 s1,232.4 s1,285.4 s
850 s24 s154.1 s228.1 s
1650 s48 s77.0 s175.0 s

Notice what happens as we add workers:

  • Parallel work decreases: More workers share the same amount of processing.
  • Per-worker overhead increases: Every additional worker adds 3 seconds of overhead.
  • Serial work and fixed overhead remain unchanged: Adding workers does not reduce these costs.

An important observation: Running the job with one worker on the cluster takes 1,285.4 seconds, while running it as a standalone process without the cluster takes only 1,242.4 seconds. The difference is 43 seconds of additional overhead. With only one worker, the cluster provides no parallel-processing benefit, but we still pay the cost of setting it up and managing that worker.

Our simulator incurs 3 seconds of overhead per worker, including launch, work assignment, and result collection.

Pause and predict · P1Commit before you read on

If we increase the cluster to 32 workers, how much total per-worker overhead will the job incur?

03

Understanding the limits of parallelism

Adding more workers can reduce processing time, but some parts of a job cannot be executed in parallel.

Let’s modify our nightly validation job to understand why. Suppose all order events arrive in a single compressed archive. Before workers can process the records, the coordinator must unpack the archive. In our example:

  • Serial work: Unpacking the archive takes 150 seconds, followed by 5 seconds to generate the final summary. Total: 155 seconds.
  • Parallel work: Validating all records takes 1,232.4 seconds on a single processor.

Without cluster overhead, the total time on one processor would be: 155 + 1,232.4 = 1,387.4 seconds

Now, imagine we could add unlimited workers without any startup or coordination overhead. As we add workers, the parallel processing time gets smaller and approaches zero. However, the 155 seconds of serial work remain unchanged, regardless of how many workers we add. Therefore, even with unlimited workers, the job cannot finish in less than 155 seconds. The maximum possible speedup is:

Maximum speedup = Single-process time ÷ Serial processing time = 1,387.4 ÷ 155 ≈ 8.95×

This is an example of Amdahl’s Law, which explains how the portion of a program that cannot be parallelised limits its maximum speedup. The serial fraction is the proportion of total processing time spent on work that cannot be divided among workers.

In our example: Serial fraction (s) = 155 ÷ 1,387.4 ≈ 0.112 (11.2%)

According to Amdahl’s Law, the theoretical maximum speedup with unlimited workers is:

Maximum speedup = 1 ÷ s = 1 ÷ 0.112 ≈ 8.95×

Even with unlimited computing resources, the job cannot exceed this theoretical speedup unless we also reduce the serial work.

Our job requires 155 seconds of serial work and 1,232.4 seconds of parallel work.

Pause and predict · P2Commit before you read on

If we could use unlimited workers with no overhead, what would be the maximum possible speedup?

What Happens When the Dataset Gets Larger?

Now suppose the number of order events triples, but the serial work remains fixed at 155 seconds. The parallel work increases from 1,232.4 seconds to: 1,232.4 × 3 = 3,697.2 seconds

The new single-process runtime becomes: 155 + 3,697.2 = 3,852.2 seconds

Pause and predict · P3Commit before you read on

If the serial work stays at 155 seconds while the parallel work triples, what happens to the theoretical maximum speedup?

04

Why more workers made the job slower

Let’s return to our nightly validation job. With 16 workers, the job completes in 175 seconds. The team now increases the cluster to 64 workers, expecting a significant improvement. But will four times as many workers make the job four times faster?

Pause and predict · P4Commit before you read on

How long will the job take with 64 workers?

05

Finding the right number of workers

We’ve seen that adding workers has two opposite effects:

  • Parallel processing time decreases because more workers share the workload.
  • Worker overhead increases because each additional worker requires coordination.

This means there is a point where these two costs are balanced, giving us the shortest possible runtime for our model. Let’s find that point.

How Runtime Changes with Worker Count

Our simulator uses the following costs:

  • Serial work + fixed overhead: 50 seconds
  • Total parallel work: 1,232.4 seconds
  • Overhead per worker: 3 seconds

For any number of workers, the runtime is: Total runtime = 50 + (3 × workers) + (1,232.4 ÷ workers)

Let’s compare different worker counts.

WorkersWorker OverheadParallel WorkTotal RuntimeBilled Core-Seconds
13.0 s1,232.4 s1,285.4 s1,285
26.0 s616.2 s672.2 s1,344
412.0 s308.1 s370.1 s1,480
824.0 s154.1 s228.1 s1,824
1648.0 s77.0 s175.0 s2,800
2060.0 s61.6 s171.6 s3,432
3296.0 s38.5 s184.5 s5,904
64192.0 s19.3 s261.3 s16,720
128384.0 s9.6 s443.6 s56,784

Core-seconds are calculated using the model’s assumption that every worker is billed for the entire job duration. Values are rounded.

Notice the pattern:

  • From 1 to 20 workers, the total runtime decreases as parallel processing becomes faster.
  • At 20 workers, the job reaches its shortest runtime of 171.6 seconds.
  • Beyond 20 workers, the increasing overhead outweighs the savings from parallel processing, so the job becomes slower.

If we plot worker count against runtime, the curve falls initially, reaches a minimum, and then rises again. This produces a U-shaped curve.

Calculating the Optimal Worker Count

For this simplified model, we can estimate the worker count that minimises runtime using:

Optimal workers = √(Total parallel work ÷ Overhead per worker)

Substituting our values:

√(1,232.4 ÷ 3) ≈ 20.3 workers

Since we need a whole number of workers, 20 workers is the best choice for minimising runtime in this example. This formula assumes evenly distributed work and no additional resource bottlenecks. Real systems may require measurements to find their optimal configuration.

The operations team asks you to choose the worker count that completes the nightly job in the shortest time.

Pause and predict · P5Commit before you read on

Which would you recommend?

What About Resource Cost?

Let’s look at the last column of the table. A core-second represents one CPU core allocated for one second. In our billing model, every worker is charged for the entire job runtime, whether it is actively processing or waiting.

Compare two configurations:

Metric8 Workers20 Workers
Total runtime228.1 s171.6 s
Billed core-seconds1,8243,432

Using 20 workers makes the job 56.5 seconds faster, but requires substantially more billing on compute resources.

Which configuration is better depends on the requirement:

  • If finishing as quickly as possible matters most, choose 20 workers.
  • If minimising compute cost matters more, fewer workers may be preferable, provided the job meets its deadline.

We’ll explore these cost and performance tradeoffs in F01.3.

Does the Optimal Worker Count Always Stay the Same?

No. The optimal number of workers changes with the workload and overhead:

  • More parallel work: A larger workload can benefit from additional workers.
  • Higher per-worker overhead: Expensive worker startup or coordination makes fewer workers more attractive.
  • Shared-resource bottlenecks: Disk, network, or other resource limits may prevent additional workers from improving performance.
Key takeaway

The goal is not to use the maximum number of workers. It is to find the worker count that provides the best balance between processing time, coordination overhead, and resource cost.

06

What this shows and its limitations

Our simulation demonstrates three important lessons:

  1. More workers introduce additional overhead: Parallel processing becomes faster as workers are added, but the cost of managing those workers also increases. Beyond a certain point, adding workers can slow the job down.
  2. Serial work limits maximum speedup: Tasks that cannot be parallelised take the same amount of time regardless of how many workers are available.
  3. Distributed execution has a cost: Running a job on a cluster with just one worker can be slower than running it as a standalone process because of additional setup and coordination overhead.

Limitations of the Model

Our simulation makes a few simplifying assumptions:

  • Sequential worker coordination: The coordinator starts workers and collects results one at a time. Real distributed engines can perform some of these operations concurrently.
  • Equal workload distribution: Every worker receives the same amount of work. In F02, we’ll explore how uneven data distribution affects performance.
  • No failures or retries: The model assumes every worker completes successfully. We’ll study failure recovery in F04.
  • No additional resource bottlenecks: The optimal-worker formula assumes processing time decreases as work is divided. Shared disks or network limits can change the result, as we saw in F01.1.
Key takeaway

The model helps explain why adding workers eventually stops improving performance. In real systems, use actual execution metrics to identify the best worker count.

07

Why one slow worker can delay the entire job

Even when work is distributed evenly, not every worker finishes at the same time. A worker might run slower because of a busy disk, limited CPU resources, or contention with another process. In distributed processing, some stages require all workers to finish before the next stage can begin. This synchronisation point is called a barrier. The slowest worker determines when the stage finishes. Let’s see how this affects our nightly validation job.

With 16 workers, each worker normally completes its share of processing in 77 seconds. Now suppose one worker takes 30% longer than the others.

Pause and predict · P6Commit before you read on

How much will the total job runtime increase?

How Can We Reduce This Problem?

One possible approach is to divide the workload into smaller tasks, allowing work to be distributed more flexibly instead of assigning one large portion to each worker. We’ll explore workload distribution and uneven partitions in F02. Another issue worth investigating is hidden serial work. A job may contain an unexpected step that runs on only one process. Such a step can limit speedup even when the rest of the work is highly parallel.

Key takeaway

In distributed systems, overall performance can be limited by the slowest worker. Always investigate slow tasks and synchronisation points when a parallel job takes longer than expected.

08

How to recognise parallelism bottlenecks

How can you tell when adding workers is no longer helping? In our simulator, look for three warning signs:

  1. Worker overhead grows faster than processing time decreases: Additional workers cost more time to manage than they save through parallel processing.
  2. Total runtime increases despite faster parallel processing: Each worker finishes its share sooner, but the complete job takes longer.
  3. Serial work limits speedup: A significant portion of runtime remains unchanged, regardless of how many workers are added.

In real distributed systems, similar symptoms include:

  • A job becomes slower after increasing the cluster size.
  • Worker startup or task scheduling takes a significant portion of total runtime.
  • Processing speed stops improving despite adding more workers.
  • Most workers finish early but must wait for one slow task.
Key takeaway

More workers are useful only when they reduce total execution time. Examine both processing time and coordination overhead to understand why scaling has stopped helping.

09

What to check before adding workers

Before increasing the number of workers, ask yourself four questions:

011 · How much work is sequential?

Identify operations that cannot be divided among workers. These determine the theoretical speedup limit.

022 · What overhead does each worker introduce?

Separate costs paid once per job from those that increase with every worker.

033 · What is the optimal worker count?

Use the runtime model as a starting estimate, then compare different worker counts through measurements.

044 · What did the additional workers actually improve?

Compare the reduction in runtime against the increase in resource consumption, measured in core-seconds.

For our simplified model, the worker count that minimises runtime is approximately:

Optimal workers = √(Total parallel work ÷ Per-worker overhead)

However, this formula assumes evenly divided work and no additional resource limits. Real systems may behave differently.

10

Check your understanding: what if worker overhead doubles?

Let’s return to the nightly validation job. Previously, each worker introduced 3 seconds of overhead. Now suppose worker startup, coordination, and result collection become more expensive, increasing the overhead to 6 seconds per worker. The total parallel work remains unchanged at 1,232.4 seconds.

If per-worker overhead doubles from 3 to 6 seconds:

  • What happens to the optimal worker count?
  • How long will the job take with 16 workers?
Pause and predict · P7Commit before you read on

Choose the correct answer:

Try It Yourself

When the F01 workbench is available, run:

Run it
python -m sim sweep --job nightly_validate --cluster lab_cluster

The simulator compares worker counts and reports their execution times. Observe the worker count with the shortest runtime and identify the two competing costs: parallel processing time and per-worker overhead.

Key takeaway

The optimal worker count depends on both the workload and the cost of managing workers. When per-worker overhead increases, using fewer workers may produce better performance.

11

Summary

Adding more workers reduces the amount of parallel work each worker must perform, but it also introduces additional coordination overhead.

A distributed job’s total runtime depends on four components:

  1. Serial work: Operations that cannot be divided among workers.
  2. Fixed overhead: Setup and coordination costs paid once per job.
  3. Parallel work: Processing time that decreases as work is distributed among more workers.
  4. Per-worker overhead: Costs that increase with the number of workers.

In our nightly validation example:

  • 16 workers completed the job in 175 seconds.
  • 64 workers increased the runtime to 261.3 seconds, approximately 86 seconds slower.
  • 20 workers provided the shortest runtime of 171.6 seconds in the original model.

We also learned that Amdahl’s Law limits the maximum speedup when part of a job cannot be parallelised. Additionally, a single slow worker can delay an entire processing stage when all workers must finish before execution continues.

Where This Matters

In production systems such as Apache Spark, similar performance problems can arise from driver-side processing, task scheduling overhead, uneven workloads, and workers waiting at stage boundaries.

We’ll explore Spark’s execution model and scheduling behavior in S01.

Key takeaway

The fastest distributed job isn’t necessarily the one with the most workers. Identify serial work, measure coordination overhead, and find the worker count that delivers the best performance for your requirements.

Sources. Capture: reference model sim 0.1, Python 3.13.16, 2026-10-13; profiles nightly_validate, lab_cluster and the page-only nightly_validate_unpack (150 s unpack step) and lab_cluster_c1x2 (6 s per worker). Amdahl, G. M. (1967), “Validity of the single processor approach to achieving large scale computing capabilities”, AFIPS Spring Joint Computer Conference, vol. 30, pp. 483–485. Gustafson, J. L. (1988), “Reevaluating Amdahl’s law”, Communications of the ACM 31(5), pp. 532–533.

Ask Colearn about this lesson

3 of 3 free questions left

Ask why serial work caps the speed-up, why extra workers eventually slow a job down, or why one slow worker holds up the rest.

Instant answers, grounded in the same verified material the diagnostic grades against.

Why can't adding more workers make every job faster?

Not every part of a job can run in parallel. Some operations must be completed sequentially, regardless of how many workers are available. This is explained by Amdahl's Law, which states that the serial portion of a job limits its maximum possible speedup.

For example, our nightly job requires 155 seconds of serial work out of 1,387.4 seconds of total single-process work. Even with unlimited workers and no overhead, the maximum speedup is: 1,387.4 ÷ 155 ≈ 8.95×

Adding workers cannot eliminate those 155 seconds of serial processing.

Why does adding more workers eventually make a job slower?

Every additional worker introduces overhead for startup, coordination, and result collection. As we increase workers:

Parallel processing time decreases because work is divided among more workers.

Coordination overhead increases because more workers need to be managed.

Eventually, the additional overhead becomes greater than the processing time saved.

In our example, 20 workers provide the shortest runtime of 171.6 seconds. Increasing to 64 workers makes the job approximately 86 seconds slower than with 16 workers.

The goal is to find the right number of workers, not the maximum number.

Why can one slow worker delay an entire distributed job?

Some processing stages cannot finish until every worker has completed its assigned work. This is called a synchronisation barrier. If one worker is slower, all the other workers may have to wait.

In our example, one worker running 30% slower increases the total job runtime by approximately 13%. The other 15 workers finish earlier and collectively spend approximately 347 core-seconds waiting. This is why identifying slow workers and balancing workloads are important for distributed processing performance.

Don’t paste credentials, personal data, or confidential production records.
Related

Workbench: L-F01 · Coming soon

Diagnostic: Test your understanding of parallelism, worker overhead, and performance bottlenecks.

What's next · Lesson F01.3Balancing Job Performance and Cost

In F01.3 · Balancing Job Performance and Cost, we’ll explore how to balance execution time and computing cost. You’ll learn how to compare worker configurations using core-seconds, understand the cost of moving data, and decide when running on a single machine may be more efficient than using a cluster.