← Delta Optimization track

Databricks · Delta Optimization · Lesson 06

Auto
compaction.

Delta cleaning up after itself: right after a write commits, the same job merges the small files it just produced into fewer, right-sized ones — synchronously, on the write cluster, no schedule required.

Runs post-commit On the write cluster Recommended auto Always on for MERGE/UPDATE/DELETE Verified Jun 2026 docs

What it is

Auto compaction is Delta tidying up immediately after a write. The moment a write commits, the same job — on the same cluster — checks whether a partition (or the table) now holds too many small files, and if so merges those small files into fewer, right-sized ones before the job ends. It runs synchronously on the write cluster, post-commit, and only ever touches files that haven't been compacted before, so it never re-chews work it already did.

The contrast with the previous lesson is the whole point. Optimized writes (Lesson 05) acts before the commit — it shuffles data so the write emits fewer, larger files. Auto compaction acts after the commit — it merges the small files that still landed on disk. They're complementary, and together they make up the "auto optimize" umbrella (Lesson 07).

Analogy
Auto compaction is the busboy clearing and consolidating tables right after each seating — the meal (write) finishes, then in the same shift the small plates get stacked into a few trays so the next service starts clean. (Optimized writes is the host seating fewer, fuller tables to begin with.)

Real-world use case
A streaming / MERGE pipeline micro-batching into a bronze table every minute. Each batch commits a few tiny files; left alone they pile up into thousands. With delta.autoOptimize.autoCompact = auto, each write's tail merges the new small files into ~128 MB+ chunks — so the table stays query-fast without a separate nightly OPTIMIZE job carrying all the load.

Why it matters

The one rule to remember Optimized writes sizes files as you write (pre-commit); auto compaction merges the small files after you write (post-commit). Turn on both for high-churn tables — and for MERGE/UPDATE/DELETE they're already on and can't be disabled.

See it work — write → commit → auto-compaction timeline

Step through a write on both sides at once. Optimized writes (left) shuffles before the commit so fewer, larger files are written. Auto compaction (right) lets the small files commit, then merges them after the commit — synchronously on the same cluster. Click a step, or use Next.

Pre-commit vs post-commit timeline

Same incoming data, two file-hygiene strategies — note when each one acts relative to the commit (amber bar).

Optimized writes

acts PRE-commit (Lesson 05)
incomingdata arrives
shuffle → writeshuffles first, so it WRITES fewer, larger files
committxn log entry — already few/large files
donenothing more to do

Auto compaction

acts POST-commit (this lesson)
incomingdata arrives
writewrites many SMALL files (no pre-shuffle)
committxn log entry — small files are now live
synchronous compactionSAME cluster merges small files → few, large

Simplified illustration of the concept. Real behavior depends on data volume, partition layout, and the configured target size; both features can be on together.

See it work — the minNumFiles threshold

Auto compaction doesn't fire on every tiny write — it waits until at least minNumFiles small files have accumulated in a partition. Click Append a batch to add small files; when the count crosses the threshold, the post-commit compaction pass fires and merges them into one right-sized file.

minNumFiles trigger simulator

A single partition. Each batch appends 2 small files. Compaction fires once the small-file count reaches the threshold.

Files in the partition
small file (uncompacted) compacted file (right-sized)
0
small files now
0
batches appended
0
compactions fired

Simplified illustration. Real triggering also weighs file sizes and the target size; minNumFiles is the minimum small-file count that makes a compaction pass worthwhile.

How it works — sub-topic by sub-topic

1 · What it does, and exactly when it runs

Auto compaction combines small files within partitions after a write succeeds. It runs synchronously on the write cluster, post-commit: the write transaction commits first, then the same job performs a compaction pass and commits that as a second transaction before finishing. The trade-off is that it adds time to the tail of the write job — for latency-critical micro-batches that's a real cost; for most pipelines the steady file hygiene is worth it.

SQL-- Turn on auto compaction at the TABLE level (applies to all writers of this table).
-- 'auto' autotunes the target file size (recommended).
ALTER TABLE main.delta_opt_demo.events
  SET TBLPROPERTIES ('delta.autoOptimize.autoCompact' = 'auto');
PySpark# Auto compaction is a TABLE PROPERTY, so any job that writes this table
# runs the post-write compaction pass.
spark.sql("""
  ALTER TABLE main.delta_opt_demo.events
  SET TBLPROPERTIES ('delta.autoOptimize.autoCompact' = 'auto')
""")

2 · "Only compacts files not previously compacted"

Each pass considers only files that haven't already been compacted by auto compaction. Once a set of small files is merged into a right-sized file, that output won't be re-merged on the next write. This makes auto compaction incremental and self-limiting — leaving it on permanently doesn't cause the cluster to keep rewriting the same data; it targets only the new small files. It's a local cleanup, not a global re-layout (that's OPTIMIZE / liquid clustering).

3 · The values: auto, true, legacy, false

auto lets Delta grow the target as the table grows instead of pinning every table to 128 MB; true/legacy give the older fixed behavior. Prefer auto for new work.

SQL-- recommended: on + autotuned target
ALTER TABLE main.delta_opt_demo.events
  SET TBLPROPERTIES ('delta.autoOptimize.autoCompact' = 'auto');

-- 'true' = on, FIXED 128 MB target · 'legacy' = alias for 'true' · 'false' = off
ALTER TABLE main.delta_opt_demo.events
  SET TBLPROPERTIES ('delta.autoOptimize.autoCompact' = 'false');  -- opt this table OUT

4 · Table property vs session config

Two control surfaces: the table property delta.autoOptimize.autoCompact travels with the table (every writer gets the same behavior); the session config spark.databricks.delta.autoCompact.enabled is set on the cluster/session and affects writes from that session. Make the table property the source of truth for production tables; use the session config deliberately. Mixing both is the classic "why is compaction running?" trap.

SQL-- SESSION-level switch (affects writes from THIS session/cluster).
-- Same value vocabulary: auto / true / legacy / false.
SET spark.databricks.delta.autoCompact.enabled = auto;
PySpark# Session/cluster scope (not per-table).
spark.conf.set("spark.databricks.delta.autoCompact.enabled", "auto")

5 · Tuning knobs: maxFileSize and minNumFiles

spark.databricks.delta.autoCompact.maxFileSize is the target/cap for the compacted output size; spark.databricks.delta.autoCompact.minNumFiles is the minimum number of small files in a partition (or the table) needed to trigger a pass. minNumFiles too low → compaction fires constantly (latency on nearly every write); too high → small files linger. Tune to your commit cadence (see the threshold simulator above).

SQL-- Don't compact until at least this many small files exist (avoid firing on tiny writes).
SET spark.databricks.delta.autoCompact.minNumFiles = 50;

-- Steer the target size of the compacted output files (here ~128 MB in bytes).
SET spark.databricks.delta.autoCompact.maxFileSize = 134217728;

6 · Always on for MERGE / UPDATE / DELETE

Auto compaction and optimized writes are always on for MERGE, UPDATE, and DELETE — and this cannot be disabled. Those operations rewrite affected files and are prime small-file producers, so the file-hygiene features are forced on as a guardrail. You can't opt a MERGE-heavy job out of the post-write compaction cost, even for ultra-low latency.

SQL-- Auto compaction + optimized writes are ALWAYS ON for MERGE/UPDATE/DELETE
-- (can't be disabled) — the small files this MERGE creates get swept up.
MERGE INTO main.delta_opt_demo.events AS t
USING staged_updates AS s
  ON t.event_id = s.event_id
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;

7 · Background auto compaction for UC managed tables

Managed = self-tidying No PO required

For Unity Catalog managed tables, a background auto compaction mode is available that does not require predictive optimization to run. It gives managed tables ongoing file hygiene even where predictive optimization isn't enabled, compacting in the background rather than only on the synchronous write path. It's distinct from both the write-cluster (synchronous) compaction and from predictive optimization.

8 · Auto compaction and predictive optimization are INDEPENDENT

Auto compaction runs synchronously on the write cluster; predictive optimization (Lesson 09) runs asynchronously on serverless compute. They're independent — use either alone or both together. Choose based on where you want the cost to land: on your write cluster (auto compaction, immediate and local) or on serverless, off the write path (predictive optimization).

9 · It does NOT replace OPTIMIZE on big tables

Auto compaction (like optimized writes) reduces the small-file problem but does not replace a periodic OPTIMIZE. For tables > 1 TB you still schedule OPTIMIZE (or let predictive optimization run it) to further consolidate, and use liquid clustering for query-key skipping. Treat auto compaction as "keeps the table from degrading between OPTIMIZE runs," not "I never need OPTIMIZE." (Lessons 04 / 07 / 09.)

10 · Migrating off the legacy config

To move from the older fixed (legacy/true) behavior to the modern default, remove the session config and unset the table property so the table falls back to the platform default. Do it deliberately — unsetting changes behavior for all writers — and re-verify with SHOW TBLPROPERTIES.

SQL-- (1) clear the session config, then (2) unset the table property.
SET spark.databricks.delta.autoCompact.enabled = false;  -- or remove from cluster config
ALTER TABLE main.delta_opt_demo.events
  UNSET TBLPROPERTIES (delta.autoOptimize.autoCompact);

-- Confirm the property is gone:
SHOW TBLPROPERTIES main.delta_opt_demo.events;

Optimized writes vs auto compaction

 Optimized writes (Lesson 05)Auto compaction (this lesson)
When it actsBefore the commit (write-time)After the commit (post-write)
HowShuffles so the write emits fewer, larger filesMerges small files that landed, within partitions
Where it runsOn the write path, during the writeSynchronously on the write cluster, post-commit
Propertydelta.autoOptimize.optimizeWritedelta.autoOptimize.autoCompact
Session configspark.databricks.delta.optimizeWrite.enabledspark.databricks.delta.autoCompact.enabled
Target size128 MB when enabledauto = autotuned · true/legacy = 128 MB
Always on for MERGE/UPDATE/DELETE?Yes (can't disable)Yes (can't disable)
Replaces OPTIMIZE?NoNo — still OPTIMIZE on > 1 TB tables

Both are the two halves of "auto optimize" (Lesson 07): optimized writes reduces how many small files appear; auto compaction merges the ones that still do.

Uses, edge cases & limitations

Uses

Edge cases an interviewer probes

Limitations

Common gotchas