Retention
Per-feed retention bounds storage on busy CI feeds by hard-deleting old/excess package versions. Off by default — deletion is irreversible.
Two-level opt-in
Section titled “Two-level opt-in”- Per-feed policy — set on
/admin/feeds(the Retention editor) or viaPUT /api/admin/feeds/{slug}/retention. A feed with no policy (or a disabled one) is never pruned. - Worker master switch —
NUGETKEEP_RETENTION_ENABLED(defaultfalse). When off, no periodic sweeps run; admins can still preview and run retention on demand from the editor/endpoints.
A policy may set either or both:
- Keep latest N — keep the N most-recent versions per package id.
- Max age (days) — prune versions older than D days.
A version is a prune candidate if it exceeds keep-N or is older than max-age.
Safety rails (always enforced)
Section titled “Safety rails (always enforced)”- The newest stable and newest prerelease of every id are never pruned.
- Prereleases only by default — stable releases are pruned only if the policy sets include stable (and even then the newest stable is kept).
- Dependency targets are never pruned — a version that another package in the feed depends on (range-aware, via the dependency graph) is protected.
- Preview before applying — the editor and
POST .../retention/previewshow exactly which versions would be pruned, deleting nothing. - Every deletion writes an audit entry (
retention-prune).
What a prune deletes
Section titled “What a prune deletes”For each selected version: the .nupkg blob, its metadata row, its indexed symbols, its
dependency edges, and its download counts.
The sweep is resilient — a per-version failure is logged and skipped, and a re-run is idempotent
(nothing left to prune).
Configuration
Section titled “Configuration”| Variable | Meaning | Default |
|---|---|---|
NUGETKEEP_RETENTION_ENABLED | Run the periodic retention worker. | false |
NUGETKEEP_RETENTION_INTERVAL | Sweep cadence (TimeSpan or seconds). | 24:00:00 |
Endpoints (admin)
Section titled “Endpoints (admin)”GET /api/admin/feeds/{slug}/retention— current policy.PUT /api/admin/feeds/{slug}/retention— set ({ enabled, keepLatest?, maxAgeDays?, includeStable }).DELETE /api/admin/feeds/{slug}/retention— clear.POST /api/admin/feeds/{slug}/retention/preview— dry-run (returns the targets; deletes nothing).POST /api/admin/feeds/{slug}/retention/run— apply now.