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 hits 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, and you end up with a load spike that comes from your own 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 flags a run that never happened and keeps run history for the ones that did, so you can see the job has gone quiet. If the machine was off, missed runs are caught up when it reconnects, up to a cap.