Field breakdown
*/30 expands to minutes 0 and 30. All other fields are wildcards, so the job fires at
00:00, 00:30, 01:00, 01:30 and so on through the day. 0,30 * * * * is exactly equivalent
and arguably clearer, since there are only two values to list.
Half-hourly is a good default for renewals
Certificate clients are the canonical example. Certbot's own guidance is to run the renewal check twice a day at a random minute, but many teams run it more frequently and rely on the client itself to no-op until renewal is actually due. A half-hourly check costs almost nothing and shortens the window in which an expiring certificate goes unnoticed.
The same reasoning applies to token refreshes, DNS updates and health reconciliation loops: the job is cheap when there is nothing to do, and the cost of being late is high.
Using it
# crontab
0,30 * * * * /usr/bin/certbot renew --quiet
# with a random offset so hosts do not stampede
$((RANDOM \% 30)),$((RANDOM \% 30 + 30)) * * * * /usr/bin/certbot renew --quiet
Crontabs do not expand shell arithmetic, so the second example only works if you generate the line
from a configuration management tool. Note also the escaped percent sign: an unescaped % in
a crontab is converted to a newline.
Offsetting to avoid the top of the hour
The top of the hour is the busiest minute on most systems — log rotation, metric flushes and every other half-hourly job all land there. Shifting a few minutes off the boundary is free:
7,37 * * * * # :07 and :37 instead of :00 and :30
Variations
| Expression | Runs |
|---|---|
| */30 * * * * | Every 30 minutes, 48 times a day. |
| 0,30 * * * * | Identical, written explicitly. |
| */30 8-18 * * 1-5 | Half-hourly during the working day. |
| 15,45 * * * * | Half-hourly, offset to the quarter marks. |
| 0 */12 * * * | Twice a day rather than twice an hour. |