> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/artifact-registry/use-artifact-registry/lifecycle-rules.md).

# Lifecycle Rules

Automate artifact retention and cleanup with policy-based lifecycle rules that soft delete stale versions on a schedule.

Lifecycle rules automate artifact retention and cleanup in Harness Artifact Registry. You define policy-based rules that identify stale or unused artifact versions and soft delete them on a recurring schedule, reducing storage costs without manual intervention.

Cleanup rules are deployment aware for *Docker registries*. When lifecycle rules are enabled, a cleanup run queries Harness Continuous Delivery (CD) and marks Docker versions that are actively deployed as **PROTECTED**. Those versions are not deleted and you do not need to create a retention rule for this protection.

***

### Rule types <a href="#rule-types" id="rule-types"></a>

Harness supports two lifecycle rule types:

* **Cleanup Rule:** Soft deletes artifact versions that match your cleanup criteria. Deleted artifacts remain recoverable during the configured recovery period.
* **Retention Rule:** Protects matching artifacts from all deletion types, including cleanup rules, manual soft delete, and manual hard delete. Retention rules are always evaluated first, regardless of rule order. A retention rule always overrides any deletion attempt.

***

### How lifecycle rules work <a href="#how-lifecycle-rules-work" id="how-lifecycle-rules-work"></a>

A lifecycle rule is a reusable policy that you create at the account, organization, or project level and attach to one or more registries. Rules do nothing until explicitly attached to a registry.

At the start of a cleanup rule execution run, the system:

1. Fetches all registries attached to the rule.
2. Scans artifact versions in each registry against the cleanup criteria.
3. For Docker registries, queries Harness CD and marks versions that are actively deployed as **PROTECTED**.
4. Applies any matching retention rules and removes protected artifacts from the candidate set.
5. Soft deletes remaining candidates that satisfy **all** enabled criteria.
6. Records the execution result with a complete audit trail.

{% hint style="info" %}
**ALL DELETIONS ARE SOFT DELETES**

There is no hard delete option in lifecycle rules. Deleted artifacts remain recoverable for the recovery period set in **Default Settings** > **Artifact Registry** at the account level. To understand how soft delete and recovery work, go to [Delete Artifacts](/artifact-registry/use-artifact-registry/manage-artifacts/soft-delete.md).
{% endhint %}

***

### Rule creation <a href="#rule-creation" id="rule-creation"></a>

Go to **Artifact Registry** > **Registries Settings** > **Lifecycle Rules** and select **+ New Lifecycle Rule**.

* Go to [Create a cleanup rule](/artifact-registry/use-artifact-registry/lifecycle-rules/create-cleanup-rule.md) to set up automated artifact deletion based on cleanup criteria.
* Go to [Create a retention rule](/artifact-registry/use-artifact-registry/lifecycle-rules/create-retention-rule.md) to protect artifacts from deletion.

<figure><img src="https://4191040053-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGmEmgYs6IUcqNiV0OEgB%2Fuploads%2Fgit-blob-1c635fb60a337d16aa79a713ce91218b459ff80f%2Flifecycle-rules-list.png?alt=media" alt="Lifecycle rules list showing rule names, types, criteria, run times, and toggle switches"><figcaption><p>Lifecycle Rules tab with active rules and execution metrics</p></figcaption></figure>

***

### Key concepts <a href="#key-concepts" id="key-concepts"></a>

* **Cleanup criteria:** You must select at least one criterion (keep last N versions, older than X days, or not downloaded in X days). When multiple criteria are enabled, **all** conditions must be true for deletion (AND logic).
* **Pattern filters:** Optionally, narrow a rule to specific packages or versions with a regular expression. Use `.*` to match any characters, then press **Enter** to add each pattern. Pattern filter fields change based on the selected package type. For example, Docker uses name and tag patterns, while Maven uses group ID, artifact name, and version patterns. Use `.*` in place of `*` when you want to match any characters. Escape a literal `.` as `\.`.

The following examples show the regular expression to enter for a common pattern:

| Pattern      | Regular expression |
| ------------ | ------------------ |
| `prod-*`     | `prod-.*`          |
| `*-prod-*`   | `.*-prod-.*`       |
| `*prod*`     | `.*prod.*`         |
| `frontend-*` | `frontend-.*`      |
| `*-service`  | `.*-service`       |
| `1.0.*`      | `1\.0\..*`         |
| `*-SNAPSHOT` | `.*-SNAPSHOT`      |

* **Scope:** Rules are created at the account, organization, or project level and attached to all registries in scope or to specific registries. Selecting **All Registries** is dynamic and automatically includes registries created after the rule. Parent-scope rules are not applied to child registries by default; enable **Show policies from parent scope** to view and attach them.
* **Schedule:** Cleanup rules run on a cron schedule (daily, monthly, yearly, or custom). Retention rules do not have a schedule; they are evaluated passively whenever a cleanup rule runs.
* **Deployment-aware protection:** Automatic for Docker registries when lifecycle rules are enabled. A cleanup run queries Harness CD and marks actively deployed Docker versions as **PROTECTED**. No retention rule is required.

{% hint style="info" %}
**DOCKER IMAGES IN PRODUCTION STAY PROTECTED**

Deployment-aware protection applies only to Docker registries. A non-Docker version is deleted when it matches the cleanup criteria, unless a retention rule matches it. Go to [Create a retention rule](/artifact-registry/use-artifact-registry/lifecycle-rules/create-retention-rule.md) to protect those artifacts.
{% endhint %}

{% hint style="info" %}
**UPSTREAM PROXY CACHE EXPIRY IS SEPARATE**

Lifecycle rules apply to artifacts published to your registries. Upstream proxy cache expiry (TTL-based cleanup of cached artifacts from upstream sources) is configured per-registry in the upstream proxy settings and operates independently.
{% endhint %}

{% hint style="info" %}
**METADATA CACHE TTL IS SEPARATE**

Metadata cache TTL controls how long package index metadata stays cached. Go to [Metadata configuration](/artifact-registry/use-artifact-registry/manage-registries/upstream-proxy.md#metadata-configuration) to configure it.
{% endhint %}

***

### Rule examples <a href="#rule-examples" id="rule-examples"></a>

The following examples illustrate common cleanup and retention setups. A pattern filter includes only the artifacts that match. To keep a package, tag, or version from deletion, create a retention rule. Go to [Key concepts](#key-concepts) for the regular expressions these examples use.

**Keep the last 10 uploaded versions, and delete versions older than 90 days**

Create a cleanup rule with both of these criteria:

* **Keep last N versions:** 10
* **Delete artifacts older than X days:** 90

Both criteria must be true before a version is deleted. Harness keeps the 10 most recently uploaded versions of each package, in upload order, not by semantic version. A version outside those 10 is deleted only when it is also older than 90 days. A version uploaded in the last 90 days stays, even when the package has more than 10 versions.

**Delete snapshot versions that were not downloaded in 30 days**

Create a cleanup rule for a package type that uses versions, such as Maven:

* **Version Patterns:** `.*-SNAPSHOT`
* **Delete if not downloaded in last X days:** 30

The rule evaluates only versions that match `.*-SNAPSHOT`. Release versions are not candidates. A matching version is deleted when it has no download in the last 30 days. After the rule runs, open the execution detail and compare **Last downloaded** with the 30-day window.

**Protect latest and production tags**

Create a retention rule on a Docker registry. Add these tag patterns:

* `latest`
* `production-.*`

A version that matches either pattern is protected from cleanup rules, manual soft delete, and manual hard delete. The retention rule has no schedule. It is applied whenever a cleanup rule runs against the same registries.

**Delete staging tags and keep production tags**

Use two rules when staging and production tags share a registry:

1. Create a cleanup rule with the tag pattern `staging-.*`. The rule includes only staging tags.
2. Create a retention rule with the tag pattern `production-.*`. Production tags stay protected even when another cleanup rule would match them.

Run a dry run on the cleanup rule before the first scheduled execution. In the execution detail, confirm that staging tags are the only deletion candidates and that production tags show **PROTECTED**.

***

### Rule management <a href="#rule-management" id="rule-management"></a>

#### Enable or disable a rule <a href="#enable-or-disable-a-rule" id="enable-or-disable-a-rule"></a>

Each rule has a toggle switch in the rules list. Use it to pause a rule without deleting it. A disabled rule retains its configuration and attachment but does not execute on schedule. Toggle it back on to resume scheduled executions.

{% hint style="info" %}
**RETENTION RULES CANNOT BE DISABLED**

Retention rules do not have a toggle switch. To stop a retention rule from protecting artifacts, you must delete it.
{% endhint %}

#### Edit or delete a rule <a href="#edit-or-delete-a-rule" id="edit-or-delete-a-rule"></a>

Select the three-dot menu (**⋮**) on a rule row to access **Edit** and **Delete** options. Cleanup rules also show a **Dry Run** option. Deleting a rule removes it and all its registry attachments. Artifacts that were already soft deleted by previous executions remain recoverable for the configured recovery period.

<figure><img src="https://4191040053-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGmEmgYs6IUcqNiV0OEgB%2Fuploads%2Fgit-blob-3596e9b64e4072804c1a3e43550b0c4db08078e7%2Flifecycle-rule-actions-menu.png?alt=media" alt="Three-dot actions menu on a lifecycle rule showing Edit, Delete, and Dry Run options"><figcaption><p>Rule actions menu with Edit, Delete, and Dry Run options</p></figcaption></figure>

***

### Use rules from parent scope <a href="#use-rules-from-parent-scope" id="use-rules-from-parent-scope"></a>

Lifecycle rules created at a parent scope (account or organization) can be applied at child scopes (organization or project). The **Created In** column always shows where each rule was originally created.

**Default view (checkbox unchecked):**

The rules list shows:

* All rules created at the current scope (for example, project-level rules)
* Parent scope rules (account or organization) that are **already applied** for this scope

**Show policies from parent scope (checkbox checked):**

Select **Show policies from parent scope** to additionally see parent scope rules that are **not yet applied** for this scope. This allows a project admin to find rules created by an account admin and apply them to their registries.

<figure><img src="https://4191040053-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGmEmgYs6IUcqNiV0OEgB%2Fuploads%2Fgit-blob-27d9a2296e12ee05654f7aa574914dec6ec40675%2Fparent-scope-policies.png?alt=media" alt="Lifecycle Rules tab with Show policies from parent scope checked, showing rules from Account, Organization, and Project scopes"><figcaption><p>Lifecycle Rules with parent scope policies visible</p></figcaption></figure>

**Edit restrictions:**

When using a rule from a parent scope, the child scope can only edit which registries the rule applies to. Criteria, schedule, and other settings cannot be changed at the child scope. The inheritance icon in the table indicates which rules come from a parent scope.

**Execution visibility:**

Execution details follow a top-down model:

* A parent scope (account) can see execution entries from all child scopes using that rule. To view artifacts deleted at child-levels, select **Show items from child scope** on the execution detail.
* A child scope (project) can only see entries from its own scope, even if the rule is owned by a parent scope.

#### Filter the rules list <a href="#filter-the-rules-list" id="filter-the-rules-list"></a>

Use the toolbar filters to narrow the view:

* **Rule Type:** Cleanup Rule or Retention Rule.
* **Registries:** Filter by specific registry.
* **Package Types:** Filter by package format.

***

### Preview and dry run <a href="#preview-and-dry-run" id="preview-and-dry-run"></a>

{% hint style="info" %}
**RUN A DRY RUN BEFORE ACTIVATING ANY CLEANUP RULE**

A dry run shows exactly which artifacts would be deleted without making any changes. This helps you validate that your criteria and filters are correct before the rule executes on schedule.
{% endhint %}

Use **Dry Run** from the rule actions menu. Dry run results appear in the **Lifecycle Rule Executions** tab alongside scheduled executions. The dry run detail view displays:

* Total artifacts scanned.
* Number of artifacts that would be deleted.
* Storage that would be reclaimed.
* Packages affected.
* A table of each version. The columns are package name, version, registry, status, size, **Uploaded at**, and **Last downloaded**.

Dry runs use identical evaluation logic to a real execution but do not mutate any data. The results show each artifact with a status of **WOULD BE DELETED** or **PROTECTED**. A Docker version shows **PROTECTED** when Harness CD reports it as actively deployed, or when a retention rule matches it.

<figure><img src="https://4191040053-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGmEmgYs6IUcqNiV0OEgB%2Fuploads%2Fgit-blob-942e84930a573790895a431ab89c519c308acf99%2Flifecycle-rule-dry-run-detail.png?alt=media" alt="Dry run execution detail showing metrics and artifact table with WOULD BE DELETED and PROTECTED statuses"><figcaption><p>Dry run execution detail: artifact-level outcomes with estimated storage saving</p></figcaption></figure>

***

### Execution history <a href="#execution-history" id="execution-history"></a>

The **Lifecycle Rule Executions** tab provides a full audit trail of every rule run. Each execution record includes:

* Rule name and target registry.
* Trigger type (scheduled or dry run).
* Status (pending, running, success, or failed). The pending status is a brief transitional state between task creation and execution pickup and is rarely visible.
* Registries affected, packages affected, versions deleted, and storage reclaimed.

You can filter executions by:

* **Status:** Failed, Running, Pending, or Success.
* **Registries:** Filter by specific registry.
* **Package Types:** Filter by package format.

Select **Show executions from parent policies** to include executions from rules inherited from a higher scope.

<figure><img src="https://4191040053-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGmEmgYs6IUcqNiV0OEgB%2Fuploads%2Fgit-blob-e0084aa422083a9d7234badbf8dcb550109eb549%2Flifecycle-rule-executions.png?alt=media" alt="Lifecycle Rule Executions tab showing execution history with status, registries affected, versions affected, and storage reclaimed"><figcaption><p>Lifecycle Rule Executions tab with status filters</p></figcaption></figure>

Select an execution to open its detail. The detail shows when the run started, how long it took, how many registries, packages, and versions it affected, and the estimated storage saved.

The packages table lists every version in the run. Use **Uploaded at** and **Last downloaded** to check why a version matched the rule:

| Column          | What it shows                                                                                                                                                                                                                                                                                                                                   |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Package name    | Package or image the version belongs to.                                                                                                                                                                                                                                                                                                        |
| Version         | Version, tag, or digest.                                                                                                                                                                                                                                                                                                                        |
| Registry        | Registry that contains the version.                                                                                                                                                                                                                                                                                                             |
| Status          | Outcome for that version. A completed run shows **Deleted** for a removed version. A dry run shows **WOULD BE DELETED** or **PROTECTED**.                                                                                                                                                                                                       |
| Size            | Size of the version.                                                                                                                                                                                                                                                                                                                            |
| Uploaded at     | When the version was uploaded. Compare this value with **Delete artifacts older than X days** and **Keep last N versions**. **Keep last N versions** keeps the N most recently uploaded versions of the package, in upload order, not by semantic version. The column shows **N/A** when Harness does not have an upload time for that version. |
| Last downloaded | When the version was last downloaded. Compare this value with **Delete if not downloaded in last X days**.                                                                                                                                                                                                                                      |

Search the table or select **Add filter** to narrow the versions. At a parent scope, select **Show items from child scope** to include versions deleted in child scopes.

***

### Notifications <a href="#notifications" id="notifications"></a>

You can receive alerts when lifecycle rule executions complete. Artifact Registry supports two notification events:

* **Lifecycle Policy Execution Completed:** Triggers when a scheduled cleanup rule finishes executing.
* **Lifecycle Policy Dry Run Execution Completed:** Triggers when a dry run finishes.

Go to [Centralised notification](https://developer.harness.io/harness-platform/use-harness-platform/notifications-alerts-and-banners/notifications/centralised-notification#artifact-registry-notifications) to configure notification rules for Artifact Registry events.

***

### Next steps <a href="#next-steps" id="next-steps"></a>

* To automate artifact deletion, go to [Create a cleanup rule](/artifact-registry/use-artifact-registry/lifecycle-rules/create-cleanup-rule.md).
* To protect critical artifacts, go to [Create a retention rule](/artifact-registry/use-artifact-registry/lifecycle-rules/create-retention-rule.md).
* To understand soft delete recovery and retention settings, go to [Delete Artifacts](/artifact-registry/use-artifact-registry/manage-artifacts/soft-delete.md).
* To review registry-level settings, go to [Configure a Registry](/artifact-registry/use-artifact-registry/manage-registries/configure-registry.md).

{% @harness-feedback/feedback %}
