Branch Lifecycle¶
Info
This feature is available with lakeFS Enterprise. Start a free trial.
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 name patterns matched against branch names (glob syntax —
*,?,[abc]). - A max age and/or a max inactivity time: at least one is required.
max_agemeasures time since branch creation;max_inactivity_timemeasures time since the last write to the branch. When both are set, both thresholds must be exceeded for the policy to apply. - An optional description.
A scheduled job runs across all repositories on a configurable cron. 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_age. - If only
max_inactivity_timeis set: the time since the branch's last write is greater thanmax_inactivity_time. - 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 fields¶
| 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 | Branches older than this become candidates. Whole number, in days via lakectl and the Web UI / in seconds over the REST API (see the note below). Must be greater than zero. At least one of max_age / max_inactivity_time must be set. |
max_inactivity_time |
conditional | Branches whose time since last write exceeds this become candidates. Same unit as max_age. AND-combined with max_age when both are set. At least one of max_age / max_inactivity_time must be set. |
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. |
Policy structure¶
This is the canonical JSON as stored and returned by the API. Values are in seconds (604800 = 7 days, 259200 = 3 days, 86400 = 1 day):
{
"policies": [
{
"id": "feature-cleanup",
"name_patterns": ["feature-*", "wip-*"],
"max_age": 604800,
"max_inactivity_time": 259200,
"description": "Auto-clean feature and WIP branches once they're old and quiet"
},
{
"id": "pol-a3f9c821",
"name_patterns": ["temp-*"],
"max_inactivity_time": 86400
}
]
}
Managing policies¶
You can manage policies from the lakeFS UI, lakectl, or the API.
- Navigate to your repository.
- Go to Settings → Branch Lifecycle.
- Click Add policy to create one, or use the Edit and Delete actions on each row to change or remove an existing one. The Max age (days) and Max inactivity time (days) fields are entered in whole days.
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. In lakectl, max_age and max_inactivity_time are whole days.
cat > policies.yaml <<'EOF'
policies:
- name_patterns: ["feature-*", "wip-*"]
max_age: 7
max_inactivity_time: 3
description: "auto-cleanup of feature and WIP branches"
- id: "temp-cleanup"
name_patterns: ["temp-*"]
max_inactivity_time: 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.
Server configuration¶
Policies are stored on the repository regardless of server configuration. The scheduled job is always wired and runs on a cron in lakefs.yaml:
branch_lifecycle.schedule(string : "0 * * * *")— Cron schedule for the job.
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 idle for lifecycle purposes.