<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Unexpected behavior of Delta VACUUM – need explanation in Data Engineering</title>
    <link>https://community.databricks.com/t5/data-engineering/unexpected-behavior-of-delta-vacuum-need-explanation/m-p/165334#M55424</link>
    <description>&lt;P&gt;Hello&lt;/P&gt;&lt;P&gt;I have a question about how VACUUM works.&lt;/P&gt;&lt;P&gt;We executed the following VACUUM command from a PySpark job:&lt;BR /&gt;spark.sql("""VACUUM catalog_name.schema_name.table_name RETAIN 168 HOURS""")&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;The Delta table has a table property retention period of 365 days, but in our PySpark code we explicitly set:&lt;BR /&gt;spark.conf.set("spark.databricks.delta.retentionDurationCheck.enabled", "false")&lt;/P&gt;&lt;P&gt;The table history shows the following entries for VACUUM:&lt;BR /&gt;version timestamp operation operationParameters operationMetrics&lt;BR /&gt;67 2026-08-07 17:08:30 VACUUM END {"status":"COMPLETED"} {"numDeletedFiles":"0","numVacuumedDirectories":"54"}&lt;BR /&gt;66 2026-08-07 17:08:29 VACUUM START {"retentionCheckEnabled":"false","defaultRetentionMillis":"31536000000"} {"numFilesToDelete":"16","sizeOfDataToDelete":"0"}&lt;/P&gt;&lt;P&gt;1. In the VACUUM START entry, operationParameters shows "retentionCheckEnabled":"false" and "defaultRetentionMillis":"31536000000" (365 days), but it does not show the explicitly specified retention (168 hours).&lt;BR /&gt;Is this a known issue/behavior?&lt;BR /&gt;Genie suggests that when VACUUM is called programmatically via PySpark (for example, spark.sql("VACUUM ... RETAIN 168 HOURS")) on certain Databricks Runtime versions, the specifiedRetentionMillis field is sometimes not logged in the table history, whereas it appears when the same command is run interactively in SQL. Can anyone confirm whether this is a known limitation or bug, and if it depends on specific Databricks Runtime versions?&lt;/P&gt;&lt;P&gt;2. Why were no files deleted?&lt;BR /&gt;We expected that, after running VACUUM ... RETAIN 168 HOURS, older versions would be removed so that time travel to those versions is no longer possible. Specifically, we have a key that was updated several months ago. After the VACUUM operation, we can still perform time travel to an older version of that key.&lt;/P&gt;&lt;P&gt;In the history:&lt;BR /&gt;operationMetrics for VACUUM START shows "numFilesToDelete":"16".&lt;BR /&gt;operationMetrics for VACUUM END shows "numDeletedFiles":"0".&lt;BR /&gt;Why were 0 files deleted, even though 16 files were reported as candidates? Under which conditions would VACUUM decide not to delete any of the candidate files, even after we disabled the retention duration check and used RETAIN 168 HOURS?&lt;/P&gt;&lt;P&gt;Any explanation of this behavior or pointers to relevant documentation would be very helpful.&lt;/P&gt;</description>
    <pubDate>Tue, 11 Aug 2026 10:02:23 GMT</pubDate>
    <dc:creator>bricks_2026</dc:creator>
    <dc:date>2026-08-11T10:02:23Z</dc:date>
    <item>
      <title>Unexpected behavior of Delta VACUUM – need explanation</title>
      <link>https://community.databricks.com/t5/data-engineering/unexpected-behavior-of-delta-vacuum-need-explanation/m-p/165334#M55424</link>
      <description>&lt;P&gt;Hello&lt;/P&gt;&lt;P&gt;I have a question about how VACUUM works.&lt;/P&gt;&lt;P&gt;We executed the following VACUUM command from a PySpark job:&lt;BR /&gt;spark.sql("""VACUUM catalog_name.schema_name.table_name RETAIN 168 HOURS""")&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;The Delta table has a table property retention period of 365 days, but in our PySpark code we explicitly set:&lt;BR /&gt;spark.conf.set("spark.databricks.delta.retentionDurationCheck.enabled", "false")&lt;/P&gt;&lt;P&gt;The table history shows the following entries for VACUUM:&lt;BR /&gt;version timestamp operation operationParameters operationMetrics&lt;BR /&gt;67 2026-08-07 17:08:30 VACUUM END {"status":"COMPLETED"} {"numDeletedFiles":"0","numVacuumedDirectories":"54"}&lt;BR /&gt;66 2026-08-07 17:08:29 VACUUM START {"retentionCheckEnabled":"false","defaultRetentionMillis":"31536000000"} {"numFilesToDelete":"16","sizeOfDataToDelete":"0"}&lt;/P&gt;&lt;P&gt;1. In the VACUUM START entry, operationParameters shows "retentionCheckEnabled":"false" and "defaultRetentionMillis":"31536000000" (365 days), but it does not show the explicitly specified retention (168 hours).&lt;BR /&gt;Is this a known issue/behavior?&lt;BR /&gt;Genie suggests that when VACUUM is called programmatically via PySpark (for example, spark.sql("VACUUM ... RETAIN 168 HOURS")) on certain Databricks Runtime versions, the specifiedRetentionMillis field is sometimes not logged in the table history, whereas it appears when the same command is run interactively in SQL. Can anyone confirm whether this is a known limitation or bug, and if it depends on specific Databricks Runtime versions?&lt;/P&gt;&lt;P&gt;2. Why were no files deleted?&lt;BR /&gt;We expected that, after running VACUUM ... RETAIN 168 HOURS, older versions would be removed so that time travel to those versions is no longer possible. Specifically, we have a key that was updated several months ago. After the VACUUM operation, we can still perform time travel to an older version of that key.&lt;/P&gt;&lt;P&gt;In the history:&lt;BR /&gt;operationMetrics for VACUUM START shows "numFilesToDelete":"16".&lt;BR /&gt;operationMetrics for VACUUM END shows "numDeletedFiles":"0".&lt;BR /&gt;Why were 0 files deleted, even though 16 files were reported as candidates? Under which conditions would VACUUM decide not to delete any of the candidate files, even after we disabled the retention duration check and used RETAIN 168 HOURS?&lt;/P&gt;&lt;P&gt;Any explanation of this behavior or pointers to relevant documentation would be very helpful.&lt;/P&gt;</description>
      <pubDate>Tue, 11 Aug 2026 10:02:23 GMT</pubDate>
      <guid>https://community.databricks.com/t5/data-engineering/unexpected-behavior-of-delta-vacuum-need-explanation/m-p/165334#M55424</guid>
      <dc:creator>bricks_2026</dc:creator>
      <dc:date>2026-08-11T10:02:23Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected behavior of Delta VACUUM – need explanation</title>
      <link>https://community.databricks.com/t5/data-engineering/unexpected-behavior-of-delta-vacuum-need-explanation/m-p/165495#M55446</link>
      <description>&lt;P&gt;Greetings&amp;nbsp;&lt;a href="https://community.databricks.com/t5/user/viewprofilepage/user-id/222050"&gt;@bricks_2026&lt;/a&gt;&amp;nbsp;, I did some digging and here is what I found.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;First, good question, and you've already pulled the right evidence from the table history. This looks like retention semantics rather than a PySpark quoting issue or a logging bug. Let me walk through both questions.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Question 1: why doesn't the history show the 168-hour retention?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;When a RETAIN clause actually drives a VACUUM run, the START entry records it as &lt;CODE&gt;specifiedRetentionMillis&lt;/CODE&gt; next to &lt;CODE&gt;retentionCheckEnabled&lt;/CODE&gt; and &lt;CODE&gt;defaultRetentionMillis&lt;/CODE&gt;. You can see an example in this thread: &lt;A href="https://community.databricks.com/t5/data-engineering/vacuum-command-runs-without-any-retention-period-even-though-the/m-p/151616" target="_blank"&gt;https://community.databricks.com/t5/data-engineering/vacuum-command-runs-without-any-retention-period-even-though-the/m-p/151616&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Your START entry has no &lt;CODE&gt;specifiedRetentionMillis&lt;/CODE&gt; and shows &lt;CODE&gt;defaultRetentionMillis: 31536000000&lt;/CODE&gt;. That tells us the run used your table's 365-day retention property, not 168 hours. And on current runtimes, that's documented behavior, not a defect. The retention window for VACUUM is now controlled by the &lt;CODE&gt;delta.deletedFileRetentionDuration&lt;/CODE&gt; table property. This applies in Databricks Runtime 18.0 and above, and for Unity Catalog managed tables it applies as far back as Runtime 13.3 LTS. Since you're using a three-level catalog.schema.table name, that likely covers you. Notice the current VACUUM syntax doesn't even document a RETAIN clause anymore: &lt;A href="https://docs.databricks.com/aws/en/sql/language-manual/delta-vacuum" target="_blank"&gt;https://docs.databricks.com/aws/en/sql/language-manual/delta-vacuum&lt;/A&gt; and &lt;A href="https://docs.databricks.com/aws/en/tables/operations/vacuum" target="_blank"&gt;https://docs.databricks.com/aws/en/tables/operations/vacuum&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;So the answer to "is this a known issue or behavior" is: known behavior, assuming your runtime and table type match the above. Disabling &lt;CODE&gt;spark.databricks.delta.retentionDurationCheck.enabled&lt;/CODE&gt; removes the safety check, but it doesn't make RETAIN override the table property. I'd confirm your exact runtime and whether the table is managed or external, since that determines which rule applies. One heads up if you ever run this on serverless: that Spark config isn't supported there at all: &lt;A href="https://kb.databricks.com/delta/the-deltaretentiondurationcheck-property-is-not-recognized-when-using-serverless-compute" target="_blank"&gt;https://kb.databricks.com/delta/the-deltaretentiondurationcheck-property-is-not-recognized-when-using-serverless-compute&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Question 2: why can you still time travel to the old key?&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Given the above, the effective retention for your run was 365 days. A key updated several months ago is well inside that window, so its old files were never eligible for deletion, and time travel to those versions still works. Fully consistent, if not what you intended. Reference on retention and time travel: &lt;A href="https://docs.databricks.com/aws/en/tables/history" target="_blank"&gt;https://docs.databricks.com/aws/en/tables/history&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;One more thing to check, because it bites people even after retention is fixed: deletion vectors. If &lt;CODE&gt;delta.enableDeletionVectors&lt;/CODE&gt; is true, an UPDATE marks old rows as deleted in metadata instead of rewriting the Parquet file. The original file stays referenced by the current version, and VACUUM never deletes files the current version references. To physically remove those old values, run &lt;CODE&gt;REORG TABLE ... APPLY (PURGE)&lt;/CODE&gt; first, then VACUUM after the retention window passes: &lt;A href="https://docs.databricks.com/aws/en/sql/language-manual/delta-reorg-table" target="_blank"&gt;https://docs.databricks.com/aws/en/sql/language-manual/delta-reorg-table&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The 16 candidates versus 0 deleted&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Those metrics describe different stages. &lt;CODE&gt;numFilesToDelete&lt;/CODE&gt; counts paths identified during the scan; &lt;CODE&gt;numDeletedFiles&lt;/CODE&gt; counts paths where the actual delete call succeeded. Your &lt;CODE&gt;sizeOfDataToDelete: 0&lt;/CODE&gt; says the 16 candidates were zero-byte objects, so they weren't your key's data files in any case; they're likely non-data paths or directory markers, and your END entry's &lt;CODE&gt;numVacuumedDirectories: 54&lt;/CODE&gt; shows directory cleanup is tracked separately. In the open-source implementation, a path that has already disappeared or whose delete returns false counts as a candidate but not a deletion: &lt;A href="https://github.com/delta-io/delta/blob/master/spark/src/main/scala/org/apache/spark/sql/delta/commands/VacuumCommand.scala" target="_blank"&gt;https://github.com/delta-io/delta/blob/master/spark/src/main/scala/org/apache/spark/sql/delta/commands/VacuumCommand.scala&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;I'll be candid that I can't pin down those 16 paths from the history alone. A DRY RUN will show you exactly what's eligible, and the KB article on reading these metrics is here: &lt;A href="https://kb.databricks.com/delta/track-deleted-files-from-vacuum-in-delta-table-history" target="_blank"&gt;https://kb.databricks.com/delta/track-deleted-files-from-vacuum-in-delta-table-history&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;What I'd do next&lt;/STRONG&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Confirm the runtime version of the job and whether the table is a Unity Catalog managed table (&lt;CODE&gt;DESCRIBE DETAIL&lt;/CODE&gt; shows this).&lt;/LI&gt;
&lt;LI&gt;Run &lt;CODE&gt;SHOW TBLPROPERTIES catalog_name.schema_name.table_name&lt;/CODE&gt; and check &lt;CODE&gt;delta.deletedFileRetentionDuration&lt;/CODE&gt;, &lt;CODE&gt;delta.enableDeletionVectors&lt;/CODE&gt;, and &lt;CODE&gt;delta.logRetentionDuration&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;If seven days is the intended window, set it deliberately: &lt;CODE&gt;ALTER TABLE ... SET TBLPROPERTIES ('delta.deletedFileRetentionDuration' = 'interval 7 days')&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;Run &lt;CODE&gt;VACUUM catalog_name.schema_name.table_name DRY RUN&lt;/CODE&gt; to inspect the candidate paths, then &lt;CODE&gt;VACUUM ... FULL&lt;/CODE&gt; without relying on RETAIN.&lt;/LI&gt;
&lt;LI&gt;If deletion vectors are enabled and you need old values physically gone, run &lt;CODE&gt;REORG TABLE ... APPLY (PURGE)&lt;/CODE&gt; first, then VACUUM once the retention window allows.&lt;/LI&gt;
&lt;LI&gt;If a DRY RUN lists real data files but VACUUM still reports zero deletions, compare those paths against cloud storage and check the compute identity's delete permissions. At that point I'd open a support ticket with both history entries and the DRY RUN output attached.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;One caution before shrinking retention: dropping from 365 days to 7 days permanently removes time travel beyond a week once VACUUM runs, and on newer runtimes time travel requests older than the property are blocked outright. Verify no readers, streaming jobs, or recovery requirements need the longer history.&lt;/P&gt;
&lt;P&gt;The takeaway: your VACUUM did exactly what the table property told it to do. Set &lt;CODE&gt;delta.deletedFileRetentionDuration&lt;/CODE&gt; to your intended window, check for deletion vectors, and the behavior should match your expectations.&lt;/P&gt;
&lt;P&gt;Regards, Louis&lt;/P&gt;</description>
      <pubDate>Wed, 12 Aug 2026 13:26:03 GMT</pubDate>
      <guid>https://community.databricks.com/t5/data-engineering/unexpected-behavior-of-delta-vacuum-need-explanation/m-p/165495#M55446</guid>
      <dc:creator>Louis_Frolio</dc:creator>
      <dc:date>2026-08-12T13:26:03Z</dc:date>
    </item>
  </channel>
</rss>

