Retention and expiry
Change how long the server keeps artifacts, change or stop the daily expiry task, and run expiry on demand.
The server keeps each artifact for BUCKET_OBJECT_EXPIRATION_HOURS, 720 hours (30 days) by default. The cache:delete-expired task runs every day at 03:00 UTC, lists every object in the store, and deletes the ones older than that. It also deletes any object whose upload time the store doesn’t report.
An artifact’s age counts from its upload. Downloads don’t reset it, so even an artifact that every build uses expires on schedule. The next run that needs it misses, runs the task, and uploads a fresh copy.
Change the retention period
On Cloudflare Workers, edit vars in apps/api/wrangler.jsonc and deploy:
{
"vars": {
"BUCKET_OBJECT_EXPIRATION_HOURS": 168,
},
}
On other platforms, set BUCKET_OBJECT_EXPIRATION_HOURS in the server’s environment. The value is a whole number of hours, at least 1.
With KV storage, the value is also each entry’s TTL.
Change the schedule
Edit scheduledTasks in apps/api/nitro.config.ts and rebuild. The key is a cron expression in UTC:
scheduledTasks: {
'0 3 * * *': ['cache:delete-expired'],
},
To stop the task, remove the entry. Artifacts then stay until you delete them, except in KV, where the TTL still applies.
Not every platform runs the schedule. Choose a platform shows which ones do.
Run expiry on demand
POST /internal/delete-expired-objects runs the same deletion and returns how many objects it deleted. It needs the TURBO_TOKEN bearer token and a JSON body. {} uses BUCKET_OBJECT_EXPIRATION_HOURS:
curl -X POST https://cache.example.com/internal/delete-expired-objects \
-H "Authorization: Bearer <your token>" \
-H "Content-Type: application/json" \
-d '{}'
{ "deleted": 42 }
To use another age for one run, send expireInHours, a number of hours that is 0 or more. {"expireInHours": 0} clears the cache. A request without a JSON body, or with a negative expireInHours, returns a 400 error.
Run expiry from a scheduler
On a platform that doesn’t run the task, call the endpoint once a day from a scheduler. This GitHub Actions workflow reads the URL from a TURBO_API variable and the token from a TURBO_TOKEN secret:
on:
schedule:
- cron: '0 3 * * *'
jobs:
expire:
runs-on: ubuntu-latest
steps:
- run: |
curl --fail -X POST "${{ vars.TURBO_API }}/internal/delete-expired-objects" \
-H "Authorization: Bearer ${{ secrets.TURBO_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{}'