Skip to content

Add scoped snapshot cleanup to invalidate command #5844

Description

@mday-io

Problem

Currently, when invalidating an environment with sqlmesh invalidate <env> -s, the command only removes the environment record and virtual layer (views/schemas), but does not clean up the physical snapshot tables.

To clean up snapshots, users must run sqlmesh janitor --ignore-ttl separately. However, this operates globally and will delete all unreferenced snapshots across the project, including those from other previously invalidated environments that haven't been cleaned up yet.

This creates a problem when you want to clean up snapshots for a specific environment without affecting other environments' snapshots.

Proposed Solution

Add a --cleanup-snapshots flag to the invalidate command that triggers scoped snapshot cleanup for only the target environment. This would:

  1. Capture the snapshot IDs from the environment being invalidated (before deletion)
  2. Identify which of those snapshots are not referenced by any other environment
  3. Delete only those exclusively-owned snapshots

Implementation Approach

The feature requires changes across multiple layers:

1. CLI Layer (sqlmesh/cli/main.py)

Add a new flag to the invalidate command:

@click.option(
    "--cleanup-snapshots",
    is_flag=True,
    help="Clean up snapshots exclusively used by this environment after invalidation",
)

2. Context Layer (sqlmesh/core/context.py)

Modify invalidate_environment to capture snapshot IDs before deletion and pass them to a scoped cleanup function when the flag is set. 1

3. State Sync Layer (sqlmesh/core/state_sync/db/facade.py)

Add a method to get expired snapshots scoped to a specific set of snapshot IDs, while still respecting the protection of snapshots referenced by other environments.

4. Snapshot State Layer (sqlmesh/core/state_sync/db/snapshot.py)

Modify get_expired_snapshots to accept an optional target_snapshot_ids parameter that restricts the query to only those IDs, while still excluding any that appear in other environments' promoted_snapshot_ids.

5. Janitor Layer (sqlmesh/core/janitor.py)

Add support for scoped snapshot deletion in delete_expired_snapshots and iter_expired_snapshot_batches.

Example Usage

# Invalidate environment and clean up its exclusively-owned snapshots
sqlmesh invalidate dev_mday_picnic_ibuk_test -s --cleanup-snapshots

This would be equivalent to running:

sqlmesh invalidate dev_mday_picnic_ibuk_test -s
sqlmesh janitor --ignore-ttl  # but scoped to only this environment's snapshots

Notes

  • The implementation must preserve the existing protection mechanism: snapshots shared with other environments (e.g., prod) must never be deleted
  • The --cleanup-snapshots flag should work with or without the -s flag
  • This feature would be particularly useful for CI/CD workflows where PR environments are frequently created and invalidated

Wiki pages you might want to explore:

Citations

File: docs/integrations/github.md (L289-292)

| Option                                | Description                                                                                                                                                                                                                                                                                                                                                                                               |  Type  | Required |
|---------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------:|:--------:|
| `invalidate_environment_after_deploy` | Indicates if the PR environment created should be automatically invalidated after changes are deployed. Invalidated environments are cleaned up automatically by the Janitor. Default: `True`                                                                                                                                                                                                             |  bool  |    N     |
| `merge_method`                        | The merge method to use when automatically merging a PR after deploying to prod. Defaults to `None` meaning automatic merge is not done. Options: `merge`, `squash`, `rebase`                                                                                                                                                                                                                             | string |    N     |

Activity

  1. self-assigned this
    on Jun 16, 2026
  2. added theissue type on Jun 16, 2026
  3. added a commit that references this issue on Jun 21, 2026
    81a0b31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

FeatureAdds new functionality

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions