repartition vs coalesce in PySpark: Shuffle, Direction and the coalesce(1) Trap
Databricks Spark Developer · Trade-off

repartition vs coalesce in PySpark: Shuffle, Direction and the coalesce(1) Trap

In PySpark, repartition performs a full shuffle to produce any partition count you ask for, evenly sized or grouped by a column. coalesce merges partitions the DataFrame already has, with no shuffle, so it is cheaper but can only lower the count and cannot even out uneven partitions. Coalesce to reduce; repartition to increase or rebalance.

Last updated October 2026.

The short version

The partition count is the parallelism of the next stage: one task per partition, one core per task. repartition(n) pays for a shuffle and can go up or down with even partitions. coalesce(n) skips the shuffle by gluing neighbors together: the cheap way down, and no way up.

This sits in Troubleshooting and Tuning, 10% of the Databricks Certified Associate Developer for Apache Spark exam per the official 30 Oct 2025 exam guide. Questions describe a symptom (idle cores, tiny files) and ask which call fixes it.

repartition: a full shuffle, any count

df.repartition(64)              # exactly 64, rows dealt out evenly
df.repartition(64, "country")   # 64, hashed on country
df.repartition("country")       # hashed; count from spark.sql.shuffle.partitions

With a number only, every row is redistributed so the new partitions come out roughly equal. With columns, rows are hash partitioned so every row with the same key lands in the same partition; with columns and no number, the count is spark.sql.shuffle.partitions, 200 by default. Either way it is a wide transformation: every row is written to shuffle files and read back over the network, and a new stage starts.

coalesce: merge what is already there

df.coalesce(100)   # 1000 partitions in, 100 out, no shuffle

Each of the 100 new partitions claims about 10 of the existing ones. That is a narrow dependency, so nothing crosses the network. Two rules follow from it:

The coalesce(1) trap: it shrinks the upstream work too

Because coalesce adds no stage boundary, the work before it runs in the same stage, in the reduced number of tasks. A heavy parse or join followed by coalesce(1) can end up running entirely on one core. The PySpark API reference says this directly: a drastic coalesce may run your computation on fewer nodes than you like, and calling repartition() instead adds a shuffle step but keeps the upstream work parallel.

So when one output file is genuinely required after heavy work, repartition(1) is the safer call.

repartition by column before a partitionBy write

write.partitionBy("country") lays the output out as one folder per value. If rows for every country are scattered across every partition, every task writes a file into every folder, and the small files multiply. Grouping the rows first means each task writes into one folder:

(df.repartition("country")
   .write.mode("overwrite")
   .partitionBy("country")
   .parquet("/data/output"))

Coalesce cannot do this, because it takes a number only and never regroups rows by key.

Side by side

 repartitioncoalesce
ShuffleYes, every rowNo: narrow dependency
DirectionUp or downDown only; a larger number is ignored
Resulting sizesEven, or grouped by keyWhatever the merged neighbors held
By columnYes: repartition("col")No, a number only
Upstream workKeeps its own parallelism (new stage)Shrinks to n tasks (same stage)
In explain()Exchange RoundRobinPartitioning or hashpartitioningCoalesce node, no Exchange

Sourced from the PySpark API reference for DataFrame.repartition and DataFrame.coalesce and the Apache Spark SQL performance tuning guide.

Decision signals

To confirm which one ran, read explain(): an Exchange is a shuffle, a Coalesce node is not. In SQL, the /*+ REPARTITION(c) */ and /*+ COALESCE(n) */ hints do the same.

What this means for the exam

Exam tip: "without a shuffle", "cheaply reduce", "fewer output files" points at coalesce. "Idle cores", "uneven partitions", "increase parallelism", "group by key before writing" points at repartition. If an option coalesces to a number higher than the current count, it does nothing.

The common distractor for raising parallelism is changing spark.sql.shuffle.partitions. That setting only applies to a shuffle's output, so it does nothing for a stage that reads files and never shuffles. Where partition counts come from (128 MB input splits, 200 shuffle partitions) is in Chapter 07, partitions and shuffles; join strategies are in the companion post on broadcast hash joins versus sort-merge joins.

To check where you stand across all seven sections, take the readiness quiz or read the section weights post.

FAQ

What is the difference between repartition and coalesce in Spark?

repartition performs a full shuffle and can raise or lower the partition count, with even partitions or rows grouped by a column. coalesce merges existing partitions without a shuffle, so it is cheaper but can only lower the count.

Can coalesce increase the number of partitions?

No. On a DataFrame, coalesce with a number larger than the current partition count leaves the count unchanged, with no error. Use repartition to increase the partition count.

Why is coalesce(1) slow on a large DataFrame?

coalesce adds no stage boundary, so the work before it also runs in one task on one core. repartition(1) adds a shuffle but keeps the upstream work parallel, which is why the PySpark docs suggest it for a drastic reduction.

Should I repartition before partitionBy when writing?

Often, yes. repartition on the same column groups each key into one partition, so each task writes into one folder instead of a small file in every folder. coalesce cannot do this because it never regroups rows by key.

Practice this hands-on

repartition versus coalesce is a trade-off chapter in Unit 4 of the Spark Developer Associate course, with the plans, the decision signals and exam-style questions built around them.

Open the chapter →