Scheduling cache warming with cron
Pre-hit expensive or cold paths on a schedule so real users never pay the first-request cost.
The problem
Cache warming exists because the first request after a cache expiry or deploy is slow — a cold homepage query, an unbuilt CDN edge object, an empty in-memory LRU after a restart. Left alone, that cost lands on whichever real user happens to hit the endpoint first (or, at deploy time, every user for a few minutes).
The naive version is a curl loop with no timeout: if the endpoint is slow specifically because the cache is cold, the warming request can hang for the request's full timeout, and a second scheduled warm-up starts stacking behind it, quietly generating a load spike disguised as a cache-warming job.
Recommended schedule
*/10 * * * *
Every 10 minutes keeps hot paths from ever fully expiring on a typical 15-minute TTL. Match the interval to your actual cache TTL — warming more often than the TTL is wasted load, less often defeats the point. See /cron for other interval expressions.
Check any expression at the cron parser, or browse more at the cron guide.
Example crontab entry
# norc: cache-warm Pre-warm top listing pages
*/10 * * * * /usr/bin/flock -n /tmp/cache-warm.lock /opt/scripts/warm.sh >> /var/log/cache-warm.log 2>&1 #!/usr/bin/env bash
set -euo pipefail
urls=(https://example.com/ https://example.com/pricing https://example.com/docs)
for u in "${urls[@]}"; do
curl -s -o /dev/null -w "%{http_code} %{time_total}s $u\n" --max-time 10 "$u"
done Failure modes to watch for
- No request timeout: a genuinely cold, slow endpoint makes the warming curl hang, and unlocked overlapping runs pile on more concurrent hits.
- Warming a deploy-triggered cache with a time-based schedule instead of an event hook — cron fires on a clock, but the cache actually goes cold on every deploy, so the schedule and the real trigger drift apart.
- Warming requests inflate analytics or rate-limit counters because they hit the same endpoint real users do without a distinguishing header.
- Warming an authenticated or personalized path with a shared/test account, silently caching one user's data for everyone.
How norc helps
norc's run history shows how long each warm-up took and whether it's creeping toward the timeout — useful for catching a cache that's drifting from "warm" to "always cold" before users notice.