Skip to content

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_age measures time since branch creation; max_idle_age measures 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_age is set: the branch's creation time is older than max_age.
  • If only max_idle_age is set: the time since the branch's last write is greater than max_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.

  1. Navigate to your repository.
  2. Go to SettingsBranch Lifecycle.
  3. 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:

lakectl branch-lifecycle get   lakefs://my-repo
lakectl branch-lifecycle clear lakefs://my-repo

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: "0 * * * *"    # standard cron (default: every hour at :00)
  • 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.