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 idle age: at least one is required.
max_agemeasures time since branch creation;max_idle_agemeasures 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_idle_ageis set: the time since the branch's last write is greater thanmax_idle_age. - If both are set: both conditions hold (AND).
Writes that bump a branch's idle 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 idle 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¶
Policies are stored as JSON:
{
"policies": [
{
"patterns": ["feature-*", "wip-*"],
"max_age": "7d",
"max_idle_age": "3d",
"description": "Auto-clean feature and WIP branches once they're old and quiet"
},
{
"patterns": ["temp-*"],
"max_idle_age": "24h"
}
]
}
| Field | Required | Description |
|---|---|---|
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. Combines the units s (seconds), m (minutes), h (hours), d (days), w (weeks): "7d", "2w", "1w3d12h". Must be greater than zero. At least one of max_age / max_idle_age must be set. |
max_idle_age |
conditional | Branches whose time since last write exceeds this become candidates. Same syntax as max_age. AND-combined with max_age when both are set. At least one of max_age / max_idle_age 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. |
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:
- patterns: ["feature-*"]
max_age: "7d"
- patterns: ["temp-*"]
max_age: "24h"
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 idle 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.