Artifact Retention
Artifact retention is how long a platform keeps an uploaded build artifact before deleting it. How GitHub Actions sets the window and what expiry breaks.
Artifact retention is the period a CI platform keeps uploaded build artifacts before deleting them, set per repository or per upload. On GitHub Actions that window defaults to 90 days, and when it closes the artifact is deleted and the download link in the run summary stops resolving.
Retention is a policy about files a job has already produced. The window governs how long the output of a run stays fetchable once the run is over.
Definition
An artifact is a file or directory that a job uploads so that a person or a later job can fetch it: a compiled binary, a test report, a coverage file, a packaged installer, a crash log. Retention is the deletion policy attached to that upload.
Three values decide what happens to any single artifact:
- A platform default, applied when nobody chooses anything.
- A ceiling set by the account, organization, or repository owner, which no upload may exceed.
- A per-upload override chosen by the workflow author, valid anywhere inside that ceiling.
The per-upload value wins when it sits inside the ceiling. A value above the ceiling is capped at the maximum and the run logs a warning, so the override can shorten a window and never extend one.
The numbers on GitHub Actions
GitHub applies one setting to both workflow artifacts and workflow logs, and the allowed range depends on repository visibility. Values below are from the GitHub Actions limits reference and the repository Actions settings documentation, checked on 2026-08-13.
| Scope | Default window | Allowed range |
|---|---|---|
| Public repository artifacts and logs | 90 days | 1 to 90 days |
| Private or internal repository artifacts and logs | 90 days | 1 to 400 days |
Per upload, via retention-days | inherits the repository setting | 1 day up to the repository maximum |
Two properties of that setting catch teams out. The first is inheritance: an enterprise limit constrains its organizations, an organization limit constrains its repositories, and a repository admin can only choose a value at or below whatever sits above. The second is that a change applies to objects uploaded afterwards. Lowering a repository from 90 days to 7 does not delete the artifacts already sitting in storage, so a cleanup pass has to remove those explicitly.
When the clock starts
The retention period for an artifact counts from the upload, rather than from the end of the workflow run. Logs are kept from the completion of the run. A long run that uploads a bundle in its first job and finishes an hour later therefore has an artifact that expires slightly before its own logs do.
Retention against eviction
Retention deletes on a schedule that is known the moment the file lands. A cache entry leaves a store by eviction instead, which is driven by how full the store is and how recently the entry was read, so no date can be read off a policy in advance. Artifacts expire. Caches get evicted. The cache eviction glossary entry covers the second mechanism.
What a retention window costs
Artifacts occupy storage for exactly as long as retention keeps them, so the steady-state footprint is a function of upload rate, artifact size, and window length:
steady state bytes = uploads per day x artifact size x retention daysTake a repository that merges 40 times a month and uploads a 2 GB installer on each merge. At the 90 day default that is roughly 1.33 uploads per day held for 90 days, or about 240 GB live at any moment. Setting retention-days: 7 on the same upload holds about 9.3 copies, or roughly 18.7 GB. The build is identical in both cases, and the deletion date is the only variable that moved.
Example
This workflow uploads two artifacts from one job and gives them different windows. The bundle is a rebuildable output that only matters until the next merge, and the test report is the record someone may want to read months later.
name: build
on:
push:
branches: [main]
jobs:
package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make dist
- name: Upload distributable bundle
uses: actions/upload-artifact@v4
with:
name: dist-bundle
path: dist/
retention-days: 7
- name: Upload test report
uses: actions/upload-artifact@v4
with:
name: junit-report
path: reports/junit.xmlThe retention-days input is documented on actions/upload-artifact, checked on 2026-08-13. The second step omits it, so junit-report inherits the repository setting.
Here is what a reader of that run sees over time, assuming the repository is left at the 90 day default.
| Day after the run | dist-bundle | junit-report |
|---|---|---|
| 0 | Listed in the run summary with a download link | Listed with a download link |
| 6 | Still downloadable | Still downloadable |
| 8 | Deleted, no longer listed in the run summary | Still downloadable |
| 91 | Deleted | Deleted, run summary lists no artifacts |
The run page itself survives. Logs, job results, and commit metadata stay put, and the artifacts section of the summary is the part that empties out.
The same transition is visible through the REST API. Each entry returned by the artifacts endpoint carries created_at, expires_at, and a boolean expired field, checked on 2026-08-13. Once expired is true the archive download no longer resolves, and any link that was pasted into a pull request comment, a chat message, or a ticket points at nothing. Anything that needs to outlive the window belongs somewhere durable: a release asset, a package registry, or an object store the team controls.
Deleting early is the other direction of the same lever. Removing an artifact from the run page or through the API frees its storage immediately rather than waiting for the window, which is the usual fix when one oversized upload is dominating a storage bill.
Related Terms
- How long GitHub Actions artifacts are kept: the default window, the per-repository maximums, and how to check what a given repository is set to.
- Cache eviction: why a cache entry disappears without an expiry date attached to it.
- Large artifact uploads on GitHub Actions: upload and download behavior when artifacts run to gigabytes.
- WarpBuild caching documentation: the cache action interface and how cache entries are stored on WarpBuild runners.
- WarpBuild pricing: per minute runner rates by runner type.
FAQ
What is artifact retention?
Artifact retention is the period a CI platform keeps uploaded build artifacts before deleting them. The window is set per repository and can be narrowed per upload. On GitHub Actions the default is 90 days, and when the window closes the artifact is deleted and its download link stops resolving.
Does artifact retention mean the same thing as cache retention?
No. Retention is a scheduled deletion with a date known at upload time. A cache entry is removed by eviction instead, which is driven by how full the store is and how recently the entry was read, so the removal date cannot be read off a policy.
Can a workflow set a retention period longer than the repository setting?
No. A retention-days value above the repository or organization maximum is capped at that maximum and the run logs a warning. The per-upload input can only shorten the window, never extend it past the ceiling the repository owner configured.
Start with $10 in free credits
Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.