The cron expression */10 * * * * runs a job every 10 minutes (6 times per hour). Covers offset syntax, thundering-herd staggering, and when to upgrade to */5.
⏰Every 10 minutes
*Any value,List separator-Range/Step1-5Range 1 through 5*/15Every 15 units*/10 * * * * runs a job six times an hour, at minutes 0, 10, 20, 30, 40, and 50, repeating every hour, every day. Over 24 hours that is 144 executions. It sits in the middle of the common step interval range: more frequent than */15 or */30, less demanding than */5.
The */10 syntax uses the step operator. In the minute field, * covers the range 0 to 59, and /10 selects every 10th value starting from 0. The result is always the same six minute marks regardless of when the daemon starts.
| Expression | Runs/hour | Runs/day | Use case |
|---|---|---|---|
*/5 * * * * |
12 | 288 | Health checks, cache refresh |
*/10 * * * * |
6 | 144 | Moderate polling, batch tasks |
*/15 * * * * |
4 | 96 | Background sync, monitoring |
*/30 * * * * |
2 | 48 | Reports, digests |
The jump from */5 to */10 cuts the run count in half. For jobs where 5 minute latency is acceptable but 15 minutes is too slow, 10 minutes is a practical middle ground that halves your resource footprint.
Many APIs do not offer push notifications. If you need to detect changes within a 10 minute window and the API has a rate limit that a 5 minute poll would strain, */10 is a good fit. You get 144 API calls per day rather than 288.
If you are processing a queue of items and a 10 minute processing lag is acceptable, */10 avoids the overhead of more frequent scheduling while keeping the queue from growing large. Monitor queue depth over time. If it grows consistently, the interval is too long.
Infrastructure checks (disk space, process counts, queue depth alerts) that trigger a notification when a threshold is crossed do not need to run every 5 minutes. A 10 minute window catches most degradation trends early enough to act without overwhelming monitoring infrastructure.
If the data you are syncing changes at most once every few minutes, a 10 minute sync interval means you are never more than one cycle behind. For reference data or configuration sync, this is usually more than sufficient.
The default */10 always fires at :00, :10, :20, :30, :40, :50. If you are running multiple jobs on a server and they all use */10, they all start simultaneously at those minute marks. This can create thundering herd spikes.
To stagger them, use the start/step syntax:
*/10 * * * * /opt/jobs/job-a # fires at :00, :10, :20...
2/10 * * * * /opt/jobs/job-b # fires at :02, :12, :22...
5/10 * * * * /opt/jobs/job-c # fires at :05, :15, :25...
Each job now has its own 2 minute offset. The load is spread evenly across each 10 minute window instead of hitting at the same time.
To confirm what */10 * * * * expands to, use Python:
from croniter import croniter
from datetime import datetime
cron = croniter("*/10 * * * *", datetime.now())
for _ in range(6):
print(cron.get_next(datetime))
This prints the next 6 execution times. All 6 will fall within the next 60 minutes, spaced exactly 10 minutes apart.
You can also verify the active schedule on a running system:
# Check what minute marks are active
echo "*/10 * * * *" | awk '{print $1}' | tr ',' '\n'
# Or use a cron parser like systemd-analyze
systemd-analyze calendar "*/10:0" 2>/dev/null || true
If you find the job consistently finishes in under 30 seconds and the output is rarely needed, consider */15. You lose 48 runs per day but gain headroom.
If you find that a 10 minute gap is causing visible staleness in a dashboard or user facing feature, drop to */5. But first ask whether a push based approach (webhooks, Server-Sent Events, WebSocket) would eliminate the polling entirely.
Nothing you paste leaves this tab. Every tool runs entirely in your browser — no upload, no server, no account.