sentinel retention
Evaluates each backup job's retention policy against the execution history and deletes the artifacts that no configured rule keeps.
Synopsis
sentinel retention [command]
sentinel retention preview [flags]
sentinel retention apply [flags]
sentinel retention on its own prints help and does nothing. Both subcommands read the job's policy from the configuration file, query the history database at history_db_path for that job's successful executions, compute the deletion candidates, and (for apply) delete each candidate through the job's own storage backend.
Subcommands
| Subcommand | Purpose |
|---|---|
preview | Computes and prints the deletion candidates without touching storage or history. Never deletes, whatever the configuration says. |
apply | Deletes the candidates from storage and removes their rows from the history database. Pass --dry-run to compute and print without deleting. |
Flags
sentinel retention
| Flag | Type | Default | Description |
|---|---|---|---|
-h, --help | bool | false | Print help for retention. |
sentinel retention preview
| Flag | Type | Default | Description |
|---|---|---|---|
-c, --config | string | ./sentinel-config.yaml | Path to the YAML configuration file. When omitted, ./sentinel-config.yaml in the working directory is used; if that file does not exist the command fails with an error naming the path it searched. |
-h, --help | bool | false | Print help for preview. |
--job | string | n/a | Restrict evaluation to one named backup job. Omit to evaluate every job that has a policy. |
preview does not accept --dry-run; passing it returns Error: unknown flag: --dry-run. Preview mode is unconditional.
sentinel retention apply
| Flag | Type | Default | Description |
|---|---|---|---|
-c, --config | string | ./sentinel-config.yaml | Path to the YAML configuration file. Same resolution as preview. |
--dry-run | bool | false | Compute and print the candidates, then stop before any storage or history mutation. |
-h, --help | bool | false | Print help for apply. |
--job | string | n/a | Restrict the run to one named backup job. An unknown name fails with Error: backup '<name>' not found and exit 1. |
sentinel retention apply permanently deletes backup artifacts from the configured storage backend and deletes their rows from the history database. There is no undo and no recycle bin. Run sentinel retention preview --config <file> --job <job> first and read the candidate list, and confirm the backups you intend to keep are verifiable with sentinel backup verify --all --config <file>.
Policy keys
Policies are configured per job under databases.<job>.retention, or once under defaults.retention. The default block is copied wholesale into any job whose own retention block sets nothing; it is never merged key by key, so a job that sets keep_last alone does not inherit the default keep_days.
| Key | Type | Default | Description |
|---|---|---|---|
keep_last | int | 0 (rule off) | Keep the N most recent successful backups. |
keep_days | int | 0 (rule off) | Keep successful backups newer than N days, measured from the current UTC time. |
dry_run | bool | false | Has no effect. See the defect note below. |
gfs.keep_daily | int | 0 (tier off) | Keep the newest backup of each of the last N occupied calendar days (UTC). |
gfs.keep_weekly | int | 0 (tier off) | Keep the newest backup of each of the last N occupied ISO weeks. |
gfs.keep_monthly | int | 0 (tier off) | Keep the newest backup of each of the last N occupied calendar months. |
gfs.keep_yearly | int | 0 (tier off) | Keep the newest backup of each of the last N occupied calendar years. |
A job whose policy sets none of these is skipped entirely when no --job is given. Only executions with status success and a recorded file path are considered; failed runs are never candidates and are never cleaned up here.
Two safety rules apply after candidate selection:
- The newest backup is always retained, even when every rule would discard it.
- The full backup that anchors the chain of the most recent backup is retained and reported as
protected active baseline.
Known defects
retention.dry_run in YAML is ignoredThe dry_run key is parsed into the configuration struct and then never read. Only the --dry-run flag on sentinel retention apply suppresses deletion. Worse, the automatic retention sweep that runs after a backup passes dry-run as false unconditionally, so a job carrying dry_run: true still has its artifacts deleted for real at the end of every sentinel backup --config <file> run. Do not rely on this key to hold a policy in observation mode; remove the policy, or use sentinel retention preview as the only safe evaluation path. The key is not entirely inert: a job whose retention block contains dry_run: true and nothing else counts as having a policy, which silently suppresses inheritance of defaults.retention for that job. Tracked as issue #157.
keep_last and keep_days intersect, they do not unionWhen both flat rules are set, a backup is deleted if either rule discards it, so a backup survives only when both rules keep it. The runbooks and the v1.3.0 release note describe a union of keeps; that description is correct for GFS against the flat rules, and wrong for the two flat rules against each other. With keep_last: 10 and keep_days: 7, an eleventh-newest backup taken two days ago is deleted even though keep_days would keep it. To get the union behaviour, configure one flat rule only. Tracked as issue #158.
Deletion removes the artifact path recorded in the history database and nothing else. The matching <artifact>.manifest.json sidecar is left behind, as is any other sidecar written next to it. On local storage the directory accumulates manifests with no artifact; on object storage the same keys accumulate and keep costing money. Sweep them yourself after an apply run, or use sentinel repair to detect the resulting inconsistency. Tracked as issue #159.
preview will not tell youArtifact deletion is implemented for local, s3, gcs, and azure only. A job on google-drive storage fails at apply time with retention delete not supported for storage type 'google-drive'. preview returns before reaching the storage layer, so it lists candidates happily for a backend that cannot delete them.
Without --job, a failure in one job is collected, the line retention completed with errors is printed to stderr, and the individual error messages are discarded. The command then exits 0. A per-job run (--job <name>) does surface the underlying error and exits 1. Use --job in any automated context where the exit code matters.
The all-jobs summary also prints total deleted: N backups in preview mode, where nothing was deleted. Read the mode from the command you typed, not from that line.
Examples
Preview every job's candidates before writing a policy into a schedule:
sentinel retention preview --config sentinel.yaml
Prints one <job>: deleted N backups line per job with a policy, then a total. In preview mode these counts are candidate counts.
Preview one job and read the reason attached to each candidate:
sentinel retention preview --config sentinel.yaml --job prod-postgres
Each line is - <path> (<bytes>) - <reason>, where the reason is exceeded keep_last, exceeded keep_days, not retained by gfs, or a comma-joined combination.
Apply one job's policy for real:
sentinel retention apply --config sentinel.yaml --job prod-postgres
Deletes each candidate artifact and its history row, then prints the same per-candidate list. Exit 1 means a deletion failed, and the list shows what was deleted before the failure.
Apply with the flag that actually suppresses deletion:
sentinel retention apply --config sentinel.yaml --job prod-postgres --dry-run
Identical output to preview, and identically harmless. This is the only dry-run switch Sentinel honours.
Example policy, with a single flat rule so the intersection defect cannot bite:
databases:
prod-postgres:
retention:
keep_days: 30
gfs:
keep_weekly: 8
keep_monthly: 12
A backup is kept when it is newer than 30 days, or when it anchors one of the last 8 ISO weeks or last 12 calendar months.
Related
- Retention: how Sentinel decides what to delete
- Configuration reference
sentinel backup, which runs the automatic post-backup sweepsentinel schedulesentinel monitorfor the history rows retention deletessentinel repairfor the inconsistencies orphaned sidecars create- CLI reference index
{/* sources: internal/cli/retention.go, internal/cli/retention_helpers.go, internal/cli/retention_cleaner.go, internal/cli/backup.go, internal/domain/retention/policy.go, internal/domain/retention/gfs.go, internal/domain/retention/types.go, internal/config/types.go, internal/cli/config_resolver.go */}