Branch Lifecycle¶
Info
Branch Lifecycle is a lakeFS Enterprise feature.
Branches in lakeFS are cheap to create, but they tend to accumulate: feature work, CI runs, experiments, and one-off explorations all leave branches behind. Stale branches clutter your repository view and keep their underlying objects out of reach of garbage collection.
Branch Lifecycle policies delete branches automatically once they match a name pattern and exceed a temporal threshold — either time since creation, time since the last write, or both. Policies are defined per repository and evaluated by a scheduled job on the server.
How it works¶
You define one or more policies on a repository. Each policy has:
- A list of glob patterns matched against branch names (glob syntax —
*,?,[abc]). - A max age and/or a max inactivity time: at least one is required.
max_agemeasures days since branch creation;max_inactivity_timemeasures days since the last write to the branch. When both are set, both thresholds must be exceeded for the policy to apply. - An optional description.
Both thresholds are expressed as a positive integer count of whole days.
A scheduled job runs across all repositories. For each repository it evaluates every branch against the policies in order — the first match wins. A branch is deleted if it matches at least one pattern of a policy and any temporal criterion the policy sets has been crossed:
- If only
max_ageis set: the branch's creation time is older thanmax_agedays. - If only
max_inactivity_timeis set: the time since the branch's last write is greater thanmax_inactivity_timedays. - If both are set: both conditions hold (AND).
Writes that bump a branch's inactivity clock include commits, merges, resets, reverts, cherry-picks, imports, branch retargets, and staging-area writes (object create/update/delete). Reads (browsing the UI, lakectl fs ls, S3 GETs through the gateway) do not count.
The repository's default branch is always exempt and cannot be matched by any pattern. Branches without a recorded creation time (created before lakeFS started tracking that field) are skipped, as are read-only repositories. Branches that have not been written to since lakeFS started tracking last-update time fall back to their creation time for inactivity calculation.
Branch deletion goes through the standard lakeFS path, so any pre-delete-branch and post-delete-branch hooks you have configured will fire.
Policy structure¶
A policy file (YAML or JSON) lists one or more policies:
policies:
- name_patterns: ["feature-*", "wip-*"]
max_age: 7
max_inactivity_time: 3
description: "Auto-clean feature and WIP branches once they're old and quiet"
- name_patterns: ["temp-*"]
max_inactivity_time: 1
| Field | Required | Description |
|---|---|---|
name_patterns |
yes | Glob patterns or literal branch names matched against branch names. At least one. OR semantics across the list. Patterns matching the default branch are rejected. |
max_age |
conditional | Days since branch creation. A branch is a candidate when its age exceeds this value. |
max_inactivity_time |
conditional | Days since the branch's last write. A branch is a candidate when its inactivity exceeds this value. |
description |
no | Free-form text shown in the UI and CLI. |
id |
no | Stable identifier (≤ 32 characters, no whitespace) used in the cron's logs. Omit it and the server assigns one (e.g. pol-a3f9c821); provide one to keep a stable handle across reapplies. Must be unique within the policies list. |
At least one of max_age / max_inactivity_time must be set; when both are set, a branch must exceed both thresholds to match the policy.
Managing policies¶
You can manage policies from the lakeFS UI, lakectl, or the API.
- Navigate to your repository.
- Go to Settings → Branch Lifecycle.
- Use Add policy, the row actions, or Delete to manage policies.
Write your policies to a YAML or JSON file and apply them. The example below uses YAML; JSON is accepted as well since it is valid YAML.
cat > policies.yaml <<'EOF'
policies:
- name_patterns: ["feature-*"]
max_age: 7
- name_patterns: ["temp-*"]
max_age: 1
EOF
lakectl branch-lifecycle set lakefs://my-repo -f policies.yaml
set returns the canonical policy list with any ids the server assigned. By default it sends the current ETag as a precondition so concurrent edits don't overwrite each other; pass --force to skip the check.
Other commands:
clear is idempotent and removes all policies for the repository.
To turn the feature off for a repository, clear its policies. A single instance runs the job at a time, even when lakeFS is deployed with multiple replicas.
Permissions¶
The following RBAC actions gate the feature:
branches:GetBranchLifecyclePolicies— read the repository's policies.branches:SetBranchLifecyclePolicies— create, update, or clear policies.
Notes¶
- Deletion is permanent. Once a branch is deleted, its uncommitted changes are gone. Committed history reachable from other branches is preserved.
- A branch can match more than one policy. Evaluation walks policies top to bottom and skips any whose temporal criteria the branch has not yet crossed. The first policy that both matches the branch's name and has its thresholds crossed wins. Whether a branch is deleted does not depend on order — as long as some applicable policy exists, the branch is deleted. Order only decides which policy is recorded as the deleter in the cron's logs, which matters when several thresholds have already been crossed at the same time.
- Tags and commits are not affected. Branch Lifecycle only deletes branch refs.
- Use hooks for guardrails. Pre-delete-branch hooks fire for lifecycle deletions, giving you a place to block deletion of branches that should not be removed.
- Everest mounts do not bump the inactivity clock until sync. Writes through a write-mode Everest mount stage in Everest's local cache; lakeFS sees no activity until
everest sync(or a commit) flushes them. A branch backed only by an active but unsynced Everest mount is considered inactive for lifecycle purposes.