Renovate Soft and Hard Package Cache Behavior
This document explains how Renovate's cache expiration works using two key configuration options: cacheHardTtlMinutes
and cacheTtlOverride
. The cacheHardTtlMinutes
setting defines the maximum time (in minutes) that any cache entry can live, acting as a global upper bound for cache expiration. The cacheTtlOverride
option allows you to specify a shorter (soft), datasource-specific cache time-to-live (TTL) for certain namespaces or providers (currently only available for npm). Together, these settings control how long cache entries are considered valid and when they are refreshed or deleted, balancing performance with data freshness. For more details, see the Renovate documentation on cacheHardTtlMinutes and cacheTtlOverride.
Exercise Overview
This exercise demonstrates the behavior of Renovate's caching mechanism by observing what happens when the same Renovate PR is rebased consecutively over time via the PR's checkbox option "If you want to rebase/retry this PR, check this box". As different cache TTLs expire (first the soft TTL, then the hard TTL), you will be able to see how cache statistics evolve from soft cache hits to hard cache hits to complete cache misses, illustrating how Renovate balances performance optimization with data freshness for npm package dependencies. The data for this analysis is obtained from the "HTTP cache statistics"
entries in the Renovate logs.
Given the the Renovate Worker Configuration below:
{
"cacheHardTtlMinutes": 5,
"cacheTtlOverride": {
"datasource-npm:cache-provider": 2
}
}
How Soft and Hard Cache TTLs Are Calculated:
The soft TTL is set per datasource (e.g.,
cacheTtlOverride
for a specific namespace).The hard TTL is the maximum of the soft TTL and the global
cacheHardTtlMinutes
value.
Timeline of Cache Behavior
⏰ 0:00 Minutes (Fresh Cache: FLUSHALL)
Cache State:
No key present
Rebase 1
Cache Stats: No Cache Hit
{
"<https://mycompany.jfrog.io>": {
"/artifactory/api/npm/fieldeng-npm-dev/express": {
"hit": 0,
"miss": 1
}
}
}
Cache State:
Key just added:
datasource-npm:cache-provider-<https://mycompany.jfrog.io/artifactory/api/npm/fieldeng-npm-dev/express>
Rebase 2
Cache Stats: Soft Cache Hit
{
"<https://mycompany.jfrog.io>": {
"/artifactory/api/npm/fieldeng-npm-dev/express": {
"hit": 0,
"miss": 0,
"localHit": 1
}
}
}
Cache State:
Key present:
datasource-npm:cache-provider-<https://mycompany.jfrog.io/artifactory/api/npm/fieldeng-npm-dev/express>
Rebase 3
Cache Stats: Soft Cache Hit
{
"<https://mycompany.jfrog.io>": {
"/artifactory/api/npm/fieldeng-npm-dev/express": {
"hit": 0,
"miss": 0,
"localHit": 1
}
}
}
Cache State:
Key present:
datasource-npm:cache-provider-<https://mycompany.jfrog.io/artifactory/api/npm/fieldeng-npm-dev/express>
⏰ 2:00 Minutes
Cache State:
Key present:
datasource-npm:cache-provider-<https://mycompany.jfrog.io/artifactory/api/npm/fieldeng-npm-dev/express>
Rebase 4
Cache Stats: Hard Cache Hit (Soft Cache Expired)
{
"<https://mycompany.jfrog.io>": {
"/artifactory/api/npm/fieldeng-npm-dev/express": {
"hit": 1,
"miss": 0,
"localMiss": 1
}
}
}
Cache State:
Key present:
datasource-npm:cache-provider-<https://mycompany.jfrog.io/artifactory/api/npm/fieldeng-npm-dev/express>
Rebase 5
Cache Stats: Hard Cache Hit (Soft Cache Expired)
{
"<https://mycompany.jfrog.io>": {
"/artifactory/api/npm/fieldeng-npm-dev/express": {
"hit": 1,
"miss": 0,
"localMiss": 1
}
}
}
Cache State:
Key present:
datasource-npm:cache-provider-<https://mycompany.jfrog.io/artifactory/api/npm/fieldeng-npm-dev/express>
⏰ 5:00 Minutes
Cache State:
No key present
Rebase 6
Cache Stats: No Cache Hit (Hard Cache Expired)
{
"<https://mycompany.jfrog.io>": {
"/artifactory/api/npm/fieldeng-npm-dev/express": {
"hit": 0,
"miss": 1
}
}
}
Cache State:
Key just added:
datasource-npm:cache-provider-<https://mycompany.jfrog.io/artifactory/api/npm/fieldeng-npm-dev/express>
Rebase 7
Cache Stats: Soft Cache Hit
{
"<https://mycompany.jfrog.io>": {
"/artifactory/api/npm/fieldeng-npm-dev/express": {
"hit": 0,
"miss": 0,
"localHit": 1
}
}
}
```**Cache State:**
Key present:
```datasource-npm:cache-provider-<https://mycompany.jfrog.io/artifactory/api/npm/fieldeng-npm-dev/express>
Summary Table
Cache TTL Config | Time | Rebase | hit | miss | localHit | localMiss | Cache Hit Type |
---|---|---|---|---|---|---|---|
Soft & Hard TTL kick in | 0 min | #1 | 0 | 1 |
|
| No Cache Hit (entries saved to cache) |
| 0 min | #2 | 0 | 0 | 1 |
| Soft Cache Hit |
| 1 min | #3 | 0 | 0 | 1 |
| Soft Cache Hit |
Soft TTL expires | 2 min |
|
|
|
|
|
|
| 3 min | #4 | 1 | 0 |
| 1 | Hard Cache Hit (Soft Cache Expired) |
| 4 min | #5 | 1 | 0 |
| 1 | Hard Cache Hit (Soft Cache Expired) |
Hard TTL expires | 5 min |
|
|
|
|
| Entries deleted from cache |
Soft & Hard TTL kick in | 6 min | #6 | 0 | 1 |
|
| No Cache Hit (entries saved to cache) |
| 7 min | #7 | 0 | 0 | 1 |
| Soft Cache Hit |