Skip to content
AI.info

ML data engineering

Table Snapshots, Compaction, and Retention

Manage table versions, physical maintenance, schema evolution, and retention without losing reproducibility.

By the end you can

A table is a logical name over changing physical evidence

Modern table formats expose snapshots, transaction logs, schema metadata and file manifests. That makes concurrent reads and updates far safer than treating a directory of files as one mutable table. It does not make the past permanent. The vendors publish the clock themselves.

Delta Lake sets VACUUM's default retention threshold for data files at 7 days. Transaction log files are deleted automatically under a default retention period of 30 days, configurable through delta.logRetentionDuration. The project warns against shortening the first of those windows: “It is recommended that you set a retention interval to be at least 7 days, because old snapshots and uncommitted files can still be in use by concurrent readers or writers to the table.”

Microsoft's Azure Databricks documentation states the same 7-day data-file default. It adds that in Databricks Runtime 18.0 and above, time travel queries are blocked when they request a version older than delta.deletedFileRetentionDuration, which defaults to 7 days. Then it says the rest in one sentence: “Don't use table history as a long-term backup solution for data archival.”

Snapshot history, deleted files, change feeds and source data all have retention boundaries. Those boundaries are measured in days. A training release therefore has to record two things: its logical identity, and the immutable versions needed to rebuild its rows. The storage defaults were never designed to cover that horizon.

Time travel works only while the referenced evidence still exists — by default, seven days of it.

Case

Delta Lake checkpoints every 10 transactions and deletes lazily

A Delta table is a directory of data objects plus a log of transaction records. The name and the bytes are separate things, and the log is what holds them together. Michael Armbrust and colleagues described that design in a 2020 VLDB paper.

The log does not grow forever. “By default, our clients write checkpoints every 10 transactions”, the paper says, compacting the log into Parquet. Deleting a row does not delete a file either. A remove action “should remain in the log and any log checkpoints as a tombstone until the underlying data object has been deleted”. The object outlives the logical delete for a while longer: “Physical deletion of the data object can happen lazily after a user-specified retention time threshold”.

That user-specified threshold is the whole game. It is the parameter whose default the documentation puts at 7 days.

The paper reports deployment “at thousands of Databricks customers that process exabytes of data per day”. So this is not a corner case in the design of one small system. It is how the evidence behind a very large share of tabular ML data is actually kept, and eventually discarded.

Comparison

Three identities that teams often collapse into one

Reproducibility improves when each identity is recorded separately.

A table name is a stable logical address. Its current contents may change with every overwrite and merge. Convenient for discovery, weak as historical identity.

A snapshot or version is a committed state under a transaction log or manifest. It is good for consistent reads, audit and rollback. But it depends on retention, and it may reference files that expiry is entitled to remove — on the 7-day Delta default or the 5-day Iceberg one.

A dataset release is a governed ML artifact: cohort, labels, transformations, splits and provenance. It names all input snapshots, carries the build code and configuration, and documents exclusions and limitations.

Only the third survives the maintenance cycle on its own terms. Only the third is obliged to say what evidence it needs, and for how long.

FigureComparison · 3 columns

Table name

A stable logical address whose current contents may change.

  • Convenient for consumers
  • Weak historical identity
  • Affected by overwrite and merge
  • Useful for discovery

Snapshot or version

A committed state of the table under a transaction log or manifest.

  • Supports consistent reads
  • Depends on retention
  • May reference removable files
  • Useful for audit and rollback

Dataset release

A governed ML artifact with cohort, labels, transformations, splits, and provenance.

  • Names all input snapshots
  • Includes build code and configuration
  • Documents exclusions and limitations
  • Best unit for model reproducibility

Visual

Table maintenance changes performance and evidence retention

Compaction and cleanup solve operational problems. Writes create files and a committed table state. Compaction rewrites small files into larger ones for efficient reads. Clustering, sorting or partition changes alter physical access patterns.

Then history expires, and the defaults are published, not mysterious. Apache Iceberg's table properties set history.expire.max-snapshot-age-ms to 432000000, which is 5 days, with history.expire.min-snapshots-to-keep at 1 and gc.enabled true. The expire_snapshots procedure defaults older_than to 5 days ago and retain_last to 1. AWS Glue's table optimizer documents the same effective default from the other side: “In the absence of this configuration, AWS Glue retains one snapshot for five days, and deletes files associated with the expired snapshots.”

The procedure is careful about what it touches: “This procedure will remove old snapshots and data files which are uniquely required by those old snapshots. This means the expire_snapshots procedure will never remove files which are still required by a non-expired snapshot.”

That care is precisely why compaction and expiry are dangerous together. Once compaction has rewritten the rows into new files, the old files are uniquely required by the old snapshots. And the old snapshots are five days from being unprotected.

The final step, archiving evidence before cleanup, has a documented cost when it is skipped. In a 2023 deployment of a Google Cloud VMware Engine Private Cloud for the Australian superannuation fund UniSuper, Google operators left one input parameter blank in an internal tool. The system assigned an unknown default fixed one-year term. At the end of that period the Private Cloud was deleted, with no customer notification.

What made restoration possible was evidence held outside the thing that expired. Google's incident review, published on 24 May 2024, says so: “Data backups that were stored in Google Cloud Storage in the same region were not impacted by the deletion, and, along with third party backup software, were instrumental in aiding the rapid restoration.” UniSuper's CEO Peter Chun and Google Cloud CEO Thomas Kurian issued a joint statement on 8 May 2024; UniSuper also had backups in place with an additional service provider.

An unattended retention default destroyed the primary copy. Only an independently held archive answered for it.

FigureProcess · 5 steps
  1. 1

    Write

    New data creates files and a committed table state.

  2. 2

    Compact

    Small files are rewritten into larger files for efficient reads.

  3. 3

    Optimize layout

    Clustering, sorting, or partition changes alter physical access patterns.

  4. 4

    Expire history

    Old snapshots or unreferenced files are removed under retention policy.

  5. 5

    Archive evidence

    Critical releases preserve manifests or immutable copies before cleanup.

Performance maintenance and evidence retention need one coordinated policy.

Key idea

Automatic schema evolution can accept a change without making it safe

A table engine may add a new column or cast a value during a merge. The write succeeds. Downstream transformations can change behavior anyway, and silently.

Scoping that permission narrowly is not this lesson's opinion. It is the vendors' written guidance about a named setting. Setting spark.databricks.delta.schema.autoMerge.enabled to true enables schema evolution for every write in the SparkSession, and Delta Lake's own documentation marks it as not recommended: “Enabling schema evolution session-wide is not recommended because it can lead to unintended schema changes across multiple operations and makes it harder to reason about which operations evolve the schema.” It directs users to WITH SCHEMA EVOLUTION, .withSchemaEvolution() or the per-write mergeSchema option instead.

Microsoft's Azure Databricks documentation labels the same Spark configuration legacy and repeats the point almost word for word: “Databricks doesn't recommend this approach for production. Setting a session-wide configuration might lead to unintended schema changes across multiple operations and makes it harder to reason about which operations evolve the schema.” It also confirms that an operation-level setting takes precedence over the session configuration. The narrow permission is always available, and it always wins.

Enable evolution at the operation that requires it. Review the semantic change. Test actual consumers. Historical snapshots may expose different schemas too, so readers need explicit compatibility rules — not the assumption that the latest schema describes every version.

Storage-level compatibility is not evidence of semantic compatibility.

Steps

Create a reproducible dataset release from mutable tables

The release has to survive routine optimization and retention work.

Pin the inputs: record table versions, object manifests or content hashes for every source. Preserve the recipe: version the query logic, parameters, code, environment and referenced lookup data. Materialize critical evidence as immutable outputs whenever upstream retention is shorter than audit needs — against a 7-day data-file default and a 5-day snapshot default, that is most of the time. Test a clean rebuild outside the original workspace and compare row-level fingerprints.

Then align retention, and note that the window may not be yours to choose. 17 CFR 240.17a-4 requires broker-dealers to preserve certain records for not less than 6 years, the first two years in an easily accessible place, and others for not less than three years.

The format was prescribed too. Until 2022 electronic records had to be kept exclusively in a non-rewriteable, non-erasable form. The SEC's amendments, adopted on 12 October 2022, opened a second route: “The SEC’s broker-dealer electronic recordkeeping rule currently requires firms to preserve electronic records exclusively in a non-rewriteable, non-erasable format, known as the write once, read many format. The amendments add an audit-trail alternative under which electronic records can be preserved in a manner that permits the recreation of an original record if it is altered, over-written, or erased.”

That alternative requires a complete time-stamped audit trail of all modifications and deletions, the date and time of each action, and the identity of the person responsible. That is a fair description of what a transaction log is. It is a precise description of what expiring one destroys.

FigureProcess · 5 steps
  1. 1. Pin inputs

    Record table versions, object manifests, or content hashes for every source.

  2. 2. Preserve the recipe

    Version query logic, parameters, code, environment, and referenced lookup data.

  3. 3. Materialize critical evidence

    Store immutable outputs when upstream retention is shorter than audit needs.

  4. 4. Test a clean rebuild

    Reconstruct the release outside the original workspace and compare row-level fingerprints.

  5. 5. Align retention

    Coordinate deletion, legal, cost, rollback, and reproducibility requirements.

Analogy

A book title, and the edition you cited

The table name is a book title. Each snapshot is a published edition. Page layout and corrections can change while the title stays constant.

A dataset release is closer to a research citation: it names the edition, the selected pages, the analysis procedure and the supplemental materials required to reproduce a result. But table snapshots may point at external files that later expire. The edition is still named in the citation, and no longer readable. That is the situation Iceberg's expire_snapshots creates by design after five days, and Delta's VACUUM after seven, for any file no unexpired snapshot still needs.

A logical name supports discovery; a reproducible claim needs an edition and retained evidence.

Retention is a risk decision, not a housekeeping default

Keeping every historical file forever is expensive, and it can conflict with privacy or deletion duties. Removing history too aggressively destroys rollback, audit and reproducibility. The second failure has a price, and the price has been assessed.

On 27 September 2022 the SEC charged 15 broker-dealers and one affiliated investment adviser over off-channel electronic communications from January 2018 through September 2021. Combined penalties came to more than $1.1 billion: eight firms at $125 million each, two at $50 million, Cantor Fitzgerald at $10 million. The CFTC settled the same conduct on the same day with affiliates of 11 financial institutions, for over $710 million, for recordkeeping and supervision failures.

The SEC's Director of Enforcement, Gurbir S. Grewal, put the reasoning plainly: “Today’s actions – both in terms of the firms involved and the size of the penalties ordered – underscore the importance of recordkeeping requirements: they’re sacrosanct. If there are allegations of wrongdoing or misconduct, we must be able to examine a firm’s books and records to determine what happened,”

Nothing there was a storage bug. The records simply were not kept.

Classify dataset releases by what goes wrong when one of them is bad. A disposable experiment, a customer-facing model and a regulated decision system need different evidence windows. Document what can be reconstructed after each retention boundary. If exact rebuild is impossible, preserve enough evidence to explain behavior and quantify the remaining uncertainty.

A retention policy should state which questions the organization will still be able to answer later.

Case

The GDPR gives retention a name: storage limitation

European data protection law makes retention a matter of principle rather than preference, and it pushes in the opposite direction from the recordkeeping rules. Article 5(1)(e) of the GDPR limits how long personal data may be kept. It must be “kept in a form which permits identification of data subjects for no longer than is necessary”. The regulation gives that principle a name of its own: “storage limitation”. Longer storage is allowed for archiving, research and statistics under Article 89(1).

Set that beside the six years in 17 CFR 240.17a-4. One body of law names a floor, another names a ceiling, and the table format's 5- or 7-day parameter knows about neither. This is why retention cannot be delegated to a storage default. A retention policy is an argument about purpose, not about storage cost.

Example

The table existed, but the training dataset did not

A team tries to reproduce a model trained eight months earlier. The table name still exists. Several things behind it have changed.

One of those changes deserves attention, because it looks like the format's business and is not. Iceberg's schema evolution is deliberately safe for the changes it supports: “Iceberg uses unique IDs to track each column in a table. When you add a column, it is assigned a new ID so existing data is never used by mistake. Formats that track columns by name can inadvertently un-delete a column if a name is reused, which violates #1.” Adds, drops, renames and reorders are independent and free of side-effects. Amazon Athena's documentation confirms the mechanism costs nothing physically: “Iceberg schema updates are metadata-only changes. No data files are changed when you perform a schema update.”

But the supported type promotions are a short, widening list: integer to big integer, float to double, and increasing the precision of a decimal. A nullable integer turned into a string code is not on it. The change this team is looking at was never a sanctioned evolution. It was a rewrite that something else had to permit.

  • Old files were compacted and expired under the storage retention policy. Against a 7-day data-file default in Delta and a 5-day snapshot default in Iceberg, eight months is far outside the window.
  • A backfill rewrote event timestamps using improved source logic.
  • The schema gained a field and turned a nullable integer into a string code — an addition Iceberg absorbs by assigning a new column ID, and a promotion that Athena's supported list (integer to big integer, float to double, increasing decimal precision) does not contain.
  • A deletion request removed rows that had been present during training.
  • The query used `latest` references rather than immutable snapshot identifiers.

Key takeaways