Web Development

*/5 * * * * - Cron Every 5 Minutes Explained

*/5 * * * * runs a job every 5 minutes, at :00, :05, :10 and so on. Here is the field-by-field reading, why */5 is not the same as 5, why */7 is not really "every 7 minutes", a table of every common interval, and the platforms that parse it differently.

By Inventive HQ Team
*/5 * * * *

Runs every 5 minutes — at :00, :05, :10 … :55 of every hour, 12 times an hour and 288 times a day, on every day of every month. Clock-aligned, not relative to when you installed it.

FieldValueMeans
1. Minute*/5every 5th minute (0, 5, 10 … 55)
2. Hour*every hour (0-23)
3. Day of month*every day (1-31)
4. Month*every month (1-12)
5. Day of week*every weekday (0-7, 0 and 7 are Sunday)

Nearby intervals, ready to copy:

Every…ExpressionEvery…Expression
minute* * * * *30 minutes*/30 * * * *
2 minutes*/2 * * * *hour0 * * * *
5 minutes*/5 * * * *2 hours0 */2 * * *
10 minutes*/10 * * * *6 hours0 */6 * * *
15 minutes*/15 * * * *12 hours0 */12 * * *
Cron BuilderRuns in your browser — nothing is uploaded.

The single mistake that trips up most people: */5 is not the same as 5. Drop the */ and you get 5 * * * *, which runs once an hour at minute 5 — a 12× difference in frequency from one missing character. It is the go-to schedule for monitoring, health checks, data synchronization, and cache warming — frequent enough to catch problems quickly without hammering your systems.

The rest of this article covers exactly how the step operator works (including the case where */N does not mean "every N minutes"), a full table of every common interval, the platforms that parse this expression differently, and how to keep a 5-minute job from tripping over itself.

Decoding */5 * * * *

The expression */5 * * * * breaks down into five fields. Only the minute field does the work; the rest are wildcards:

How the cron expression */5 * * * * is read The five cron fields are minute, hour, day of month, month, and day of week. The minute field holds the step value slash-five, which fires on minutes 0, 5, 10 through 55. A marker hops across those minute marks below. reading */5 * * * * field by field */5 * * * * minute every 5 min hour every hour day of month every day month every month weekday every day the minute field fires on every mark divisible by 5: 0 5 10 15 20 25 30 35 40 45 50 55 12 runs per hour · 288 runs per day · aligned to the clock 5 * * * * (no slash) runs once an hour, only at :05 the */ is what makes it an interval, not a fixed minute
  • */5 - Minute field: Every 5 minutes
  • * - Hour field: Every hour
  • * - Day of month field: Every day
  • * - Month field: Every month
  • * - Day of week field: Every day of the week

The key is understanding the */5 syntax in the minute field.

*/5 vs 5: the one-character mistake

This is the trap worth burning into memory, because the two expressions look almost identical and behave nothing alike:

ExpressionSlash?When it runsRuns per day
*/5 * * * *step operatorEvery 5 minutes (:00, :05, :10 … :55)288
5 * * * *fixed valueOnce an hour, only at minute 5 (1:05, 2:05 …)24

The slash (/) is what turns a value into an interval. Without it, a bare number is a single fixed minute. So 5 * * * * is not "every 5 minutes" — it is "at 5 minutes past every hour." If a job you expected to run constantly is only firing once an hour, a missing */ is the first thing to check.

How the Slash Operator Works

The slash (/) creates step values or intervals. When you write */5 in the minute field, you're telling cron:

"Start at the minimum value (0), then step by 5."

This means the task executes when the minute value is divisible by 5 with no remainder:

  • Minute 0 (12:00, 1:00, 2:00, etc.)
  • Minute 5 (12:05, 1:05, 2:05, etc.)
  • Minute 10 (12:10, 1:10, 2:10, etc.)
  • Minute 15 (12:15, 1:15, 2:15, etc.)
  • Minute 20 (12:20, 1:20, 2:20, etc.)
  • Minute 25 (12:25, 1:25, 2:25, etc.)
  • Minute 30 (12:30, 1:30, 2:30, etc.)
  • Minute 35 (12:35, 1:35, 2:35, etc.)
  • Minute 40 (12:40, 1:40, 2:40, etc.)
  • Minute 45 (12:45, 1:45, 2:45, etc.)
  • Minute 50 (12:50, 1:50, 2:50, etc.)
  • Minute 55 (12:55, 1:55, 2:55, etc.)

That's 12 times per hour, 288 times per day (24 hours × 12 executions).

What */5 Actually Means

The */5 pattern is shorthand for 0-59/5, which means "every 5 minutes within the range 0 to 59." The asterisk, in the words of the crontab(5) man page, "always stands for 'first-last'" — so it expands to the full range of the field, and the /5 then steps through that range.

The task doesn't run at random 5-minute intervals — it runs at predictable, clock-aligned times. If you start your cron job at 3:17 PM, it won't run at 3:17, then 3:22, then 3:27. Instead, it waits until the next 5-minute mark (3:20 PM), then runs at 3:20, 3:25, 3:30, and so on.

The Gotcha: */N Divides the Field, It Does Not Repeat Forever

This is the part that causes real incidents, and it is worth being precise about. A step value is evaluated only inside its own field, and the field restarts at its minimum when it rolls over. The crontab(5) man page says so directly:

"Please note that steps are evaluated just within the field they are applied to. For example */23 in hours field means to execute the job on the hour 0 and the hour 23 within a calendar day."

Read that example carefully: */23 in the hour field is not "every 23 hours." It fires at hour 0 and hour 23 — a 23-hour gap, then a 1-hour gap, then repeat.

The same trap applies to minutes. */7 * * * * looks like "every 7 minutes." It is not:

*/7 * * * *   →  :00 :07 :14 :21 :28 :35 :42 :49 :56  then  :00 of the next hour

That is 9 runs per hour, and the gap between the last run at :56 and the next at :00 is 4 minutes, not 7. The interval is uneven forever.

*/5 gets away with it purely because 60 is divisible by 5. The last run is at :55 and the next is at :00 — exactly 5 minutes later, so the cadence really is uniform.

The rule: a minute step is evenly spaced only when it divides 60, and an hour step only when it divides 24.

FieldRangeStep values that stay evenly spaced
Minute0-591, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30
Hour0-231, 2, 3, 4, 6, 8, 12

Anything else — */7, */8, */9, */11, */13, */25 on minutes, or */5, */7, */23 on hours — produces a short final gap at every rollover. If you genuinely need "every 7 minutes" with a constant interval, cron cannot express it; use a systemd timer with OnUnitActiveSec=7min, a scheduler that supports true rate expressions, or have the job schedule its own next run.

A second, related trap: stepping the hour field while leaving the minute field as *.

* */2 * * *     wrong — fires every minute, for a full hour, every 2 hours (720 runs/day)
0 */2 * * *     right — fires once, at the top of every second hour (12 runs/day)

Whenever you put a step on the hour, pin the minute to a fixed value.

Common Use Cases for Every 5 Minutes

Running tasks every 5 minutes strikes a balance between frequency and system load. Here's where this pattern shines:

System Monitoring

Monitoring systems often check health status every 5 minutes:

*/5 * * * * /usr/local/bin/check-server-health.sh

This frequency catches problems quickly without overwhelming your monitoring infrastructure. For critical systems, you might go tighter (every minute), but for most applications, 5-minute intervals provide adequate responsiveness.

API Data Synchronization

Pulling data from external APIs on a regular cadence:

// Node.js with node-cron
cron.schedule('*/5 * * * *', async () => {
  try {
    const data = await fetchExternalAPI();
    await saveToDatabase(data);
    console.log('Data synced at', new Date());
  } catch (error) {
    console.error('Sync failed:', error);
  }
});

This ensures your application has reasonably fresh data without hitting rate limits that might come from per-minute requests.

Advertisement

Cache Warming

Regenerating frequently-accessed cached data:

# Python with APScheduler
@scheduler.scheduled_job(CronTrigger.from_crontab('*/5 * * * *'))
def warm_cache():
    popular_pages = get_popular_pages()
    for page in popular_pages:
        regenerate_cache(page)

Queue Processing

Checking for pending jobs in a work queue:

// Java Spring
@Scheduled(cron = "0 */5 * * * *")  // Note: Spring uses 6 fields
public void processQueue() {
    List<Job> pendingJobs = jobRepository.findPending();
    for (Job job : pendingJobs) {
        processJob(job);
    }
}

Log Analysis

Aggregating or analyzing recent log entries:

*/5 * * * * /usr/local/bin/analyze-logs.py --last 5m

The 5-minute interval matches the time window being analyzed, ensuring continuous coverage without overlap.

Availability Checks

Testing website or service availability:

cron.schedule('*/5 * * * *', async () => {
  const isUp = await checkServiceHealth('https://example.com');
  if (!isUp) {
    await sendAlert('Service is down!');
  }
});

Common Interval Variations

While every 5 minutes is popular, other intervals serve different needs. Here is the full cheat sheet — minute-step and hour-step patterns side by side. Note the pattern for hours: you put the step on the hour field and pin the minute to 0, otherwise the job fires every minute inside each chosen hour.

IntervalCron expressionFires atRuns/day
Every minute* * * * *every minute1,440
Every 2 minutes*/2 * * * *:00, :02, :04 … :58720
Every 5 minutes*/5 * * * *:00, :05, :10 … :55288
Every 10 minutes*/10 * * * *:00, :10, :20 … :50144
Every 15 minutes*/15 * * * *:00, :15, :30, :4596
Every 30 minutes*/30 * * * *:00, :3048
Every hour0 * * * *top of every hour24
Every 2 hours0 */2 * * *00:00, 02:00, 04:00 …12
Every 6 hours0 */6 * * *00:00, 06:00, 12:00, 18:004
Every 12 hours0 */12 * * *00:00, 12:002

The individual variations below add context on when each one is the right choice:

Every Minute: * * * * *

* * * * *

The most frequent possible schedule—1,440 executions per day. Use sparingly:

  • Critical system monitoring
  • Real-time data processing
  • High-frequency trading systems
  • Urgent queue processing

Warning: Every-minute execution can strain resources. Ensure your task completes in under 60 seconds to avoid overlapping runs.

Every 2 Minutes: */2 * * * *

*/2 * * * *

Runs at minutes 0, 2, 4, 6, 8... 58 (30 times per hour). A middle ground between every minute and every 5 minutes for moderately urgent tasks.

Every 10 Minutes: */10 * * * *

*/10 * * * *

Runs at minutes 0, 10, 20, 30, 40, 50 (6 times per hour). Good for:

  • Less critical monitoring
  • Periodic data fetches
  • Regular database maintenance
  • Report generation

Every 15 Minutes: */15 * * * *

*/15 * * * *

Runs at minutes 0, 15, 30, 45 (4 times per hour). Common for:

  • Scheduled backups during business hours
  • Regular status updates
  • Moderate-frequency synchronization

This interval aligns nicely with quarter-hours, making it easy to remember and communicate.

Every 30 Minutes: */30 * * * *

*/30 * * * *

Runs at minutes 0 and 30 (twice per hour). Popular for:

  • Hourly-ish tasks that don't need precision
  • Resource-intensive operations
  • Less frequent data updates

Note: */30 is equivalent to 0,30 but more semantic—it clearly states "every 30 minutes."

Every Hour: 0 * * * *

0 * * * *

Runs at the top of every hour (XX:00). The next step up from minute-based intervals:

  • Hourly reports
  • Log rotation
  • Cache clearing
  • Scheduled emails

Restricting Intervals to Specific Times

The real power comes from combining interval patterns with time restrictions:

Every 5 Minutes During Business Hours

*/5 9-17 * * 1-5

Runs every 5 minutes, but only from 9 AM to 5 PM on weekdays. Perfect for:

  • Business hours monitoring
  • Support ticket checking
  • API rate limit management (spread requests during work hours only)

Every 10 Minutes at Night

*/10 0-6 * * *

Runs every 10 minutes from midnight to 6 AM. Useful for:

  • Off-hours maintenance
  • Background processing during low traffic
  • Database optimization

Every 15 Minutes on Weekdays

*/15 * * * 1-5

Every 15 minutes, but only Monday through Friday:

  • Business day automation
  • Weekday-only integrations
  • Office hours tasks

Every 5 Minutes for a Few Hours

*/5 8-12 * * *

Every 5 minutes from 8 AM to noon:

  • Morning rush monitoring
  • Limited-time promotions
  • Targeted processing windows

Performance Considerations

Running tasks every 5 minutes seems innocent, but 288 daily executions add up:

Execution Time

Ensure your task completes in under 5 minutes. If not, implement concurrency controls to prevent overlapping executions:

let isRunning = false;

cron.schedule('*/5 * * * *', async () => {
  if (isRunning) {
    console.log('Previous execution still running, skipping...');
    return;
  }

  isRunning = true;
  try {
    await performTask();
  } finally {
    isRunning = false;
  }
});

Resource Impact

Each execution consumes CPU, memory, network, or database resources. For 288 daily runs:

  • Database queries should be optimized
  • API calls should respect rate limits
  • Logs should be manageable in volume
  • Memory leaks compound quickly

Error Handling

With frequent execution, errors happen. Implement proper logging and alerting:

import logging

@scheduler.scheduled_job(CronTrigger.from_crontab('*/5 * * * *'))
def frequent_task():
    try:
        result = perform_operation()
        logging.info(f'Task completed successfully: {result}')
    except Exception as e:
        logging.error(f'Task failed: {e}')
        # Don't alert on every failure—implement threshold-based alerting
        if consecutive_failures > 3:
            send_alert(f'Task has failed 3+ times: {e}')

Rate Limiting

If your 5-minute task calls external APIs, verify the rate limit:

  • 12 calls per hour
  • 288 calls per day
  • ~8,640 calls per month

Ensure this fits within API quotas. If not, consider less frequent intervals.

Alternatives to Fixed Intervals

Sometimes fixed 5-minute intervals aren't ideal:

Event-Driven Triggers

Instead of checking for new data every 5 minutes, have the data source trigger your task via webhooks or message queues. This eliminates unnecessary checks and provides instant response.

Exponential Backoff

For failure scenarios, consider increasing interval on repeated failures:

  • First failure: Retry after 1 minute
  • Second failure: Retry after 5 minutes
  • Third failure: Retry after 15 minutes
  • Fourth failure: Retry after 1 hour

Dynamic Scheduling

Adjust frequency based on load or time of day:

// Pseudo-code example
const interval = isDaytime() ? '*/5' : '*/30';
cron.schedule(`${interval} * * * *`, task);

Not Every Scheduler Parses */5 * * * * the Same Way

"Cron syntax" is not one syntax. The five-field expression above is standard Unix cron, and several popular schedulers accept something that looks similar but is not identical. Pasting a five-field expression into a six-field parser is a classic deploy-day failure.

PlatformFields*/5 * * * * valid?Notes
crontab (Vixie/cronie)5YesThe baseline. No seconds field.
Kubernetes CronJob5YesStandard cron. .spec.schedule.
Cloudflare Workers5YesCron Triggers use standard 5-field syntax.
GitHub Actions5YesMinimum interval is 5 minutes — */5 is the floor. Runs in UTC by default. Scheduled runs can be delayed under load, so never rely on exact timing.
systemd timersn/aNoUses OnCalendar= calendar events, not cron. Every 5 minutes is OnCalendar=*:0/5.
AWS EventBridge6NoSix fields including Year, and you cannot use * in both Day-of-month and Day-of-week — one must be ?.
Quartz / Spring @Scheduled6-7NoLeading seconds field, so a five-field expression shifts every value by one position.

systemd, every 5 minutes:

[Timer]
OnCalendar=*:0/5
Persistent=true

AWS EventBridge, every 5 minutes on weekdays between 08:00 and 17:55 UTC — note the 0/5 start/step form AWS documents, the ?, and the trailing year field:

cron(0/5 8-17 ? * MON-FRI *)

EventBridge also offers rate expressions, which sidestep cron entirely:

rate(5 minutes)

Two AWS constraints worth knowing: all scheduled events run in UTC+0, and the finest resolution is one minute — "cron expressions that lead to rates faster than 1 minute are not supported."

Quartz / Spring, where the first field is seconds:

0 */5 * * * *

The general rule when moving an expression between systems: count the fields first. If the target expects six and you give it five, it will either reject the expression or silently shift every field by one position — which is how "every 5 minutes" quietly becomes "every 5 seconds" or "at 05:00."

Verify Before You Deploy

A cron expression is a piece of production configuration that nothing typechecks. Confirm it before it ships.

1. Translate it. Paste the expression into the Cron Expression Builder and read the plain-English description and the next run times back. If the description does not match your intent, stop there.

2. Check the next few fire times, not just the first. Most */N mistakes are invisible in the first two runs and only appear at the rollover — an every-7-minutes schedule looks perfect until :56.

3. Test with a faster schedule, then switch. Run * * * * * while you are validating the script, and change to */5 * * * * once the job itself is proven:

* * * * *    # test version — validates the command, not the schedule
*/5 * * * *  # production version

4. Confirm cron actually accepted it. crontab -l shows what is installed. On Debian and Ubuntu, grep CRON /var/log/syslog shows what actually fired; on RHEL-family systems use journalctl -u crond. A job that never appears in the log is not a schedule problem — it never ran at all.

5. Check the timezone. Cron uses the server's local time unless the crontab sets CRON_TZ. GitHub Actions and AWS EventBridge both default to UTC. A schedule that is correct in one timezone and deployed into another is one of the most common "it ran at the wrong time" causes, and daylight saving transitions make it worse.

6. Keep a manual trigger. Being able to run the task on demand — rather than waiting for the next mark — makes every subsequent debugging session faster:

// HTTP endpoint for manual execution
app.post('/api/trigger-task', async (req, res) => {
  await task();
  res.json({ status: 'executed' });
});

Getting the Syntax Right

Creating the perfect interval expression is crucial. A small typo can mean the difference between every 5 minutes and every 5 hours. Use our Cron Expression Builder to visually create and validate your expression. You'll see exactly when your task will run, with plain English translations that eliminate ambiguity.

Whether you need standard */5 * * * * or a complex variation restricted to specific hours and days, getting the cron syntax right ensures your automation runs exactly when you need it—no more, no less.

Frequently Asked Questions

What does */5 * * * * mean in cron?

It runs a job every 5 minutes. The five fields are minute, hour, day of month, month, and day of week. Only the minute field carries the step value */5, which means "start at 0 and fire on every minute divisible by 5" — that is minutes 0, 5, 10, 15, up to 55. The four asterisks after it mean every hour, every day, every month, and every weekday, so the job fires 12 times an hour, 288 times a day, at clock-aligned times like 3:00, 3:05, and 3:10.

What is the difference between */5 and 5 in a cron expression?

They are completely different schedules. */5 * * * * uses the slash step operator and runs every 5 minutes (12 times per hour). 5 * * * * has no slash, so the 5 is a single fixed value: it runs once per hour, only at minute 5 (1:05, 2:05, 3:05, and so on) — 24 times per day. Forgetting the */ is one of the most common cron mistakes and turns "every 5 minutes" into "once an hour."

How many times a day does */5 * * * * run?

288 times. It fires 12 times every hour (at minutes 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55), and 12 × 24 hours = 288 executions per day. Over a month that is roughly 8,640 runs, which matters if the job calls a rate-limited external API.

Does */5 run 5 minutes after the job starts?

No. Cron aligns to the wall clock, not to when you deployed or started the job. */5 * * * * always fires at fixed marks like :00, :05, and :10. If you install it at 3:17, the next run is 3:20 (the next multiple of 5), not 3:22. It is not a rolling 5-minute timer.

How do I write a cron job that runs every 30 minutes?

Use */30 * * * *, which fires at minute 0 and minute 30 of every hour (twice an hour). It is equivalent to 0,30 * * * * but reads more clearly as "every 30 minutes." For every 15 minutes use */15 * * * *, and for every 10 minutes use */10 * * * *.

How do I run a cron job every 2 hours instead of every 5 minutes?

Put the step on the hour field and pin the minute: 0 */2 * * * runs at the top of every second hour (00:00, 02:00, 04:00, and so on). A common mistake is writing * */2 * * *, which leaves the minute as a wildcard and fires every minute for a whole hour, every 2 hours. Always set the minute to a fixed value when you step the hour.

Can I run every 5 minutes only during business hours?

Yes. Combine the minute step with an hour range and a weekday range: */5 9-17 * * 1-5 runs every 5 minutes from 9 AM to 5 PM, Monday through Friday. The 9-17 restricts the hour field and 1-5 restricts the day-of-week field (Monday is 1, Friday is 5), so the every-5-minute cadence only applies inside that window.

Does */7 * * * * really run every 7 minutes?

No. It fires at minutes 0, 7, 14, 21, 28, 35, 42, 49, and 56, then the hour rolls over and it fires again at minute 0 — only 4 minutes later. Step values are evaluated only within their own field, and the minute field restarts at 0 every hour. A minute step is evenly spaced only if it divides 60 (1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30). */5 works precisely because 60 is divisible by 5.

Why does */5 * * * * not work in AWS EventBridge or Quartz?

Because they do not use five fields. AWS EventBridge cron expressions have six fields including a Year field, and you cannot put * in both Day-of-month and Day-of-week — one must be ?, as in cron(0/5 * * ? * *). Quartz and Spring @Scheduled put a seconds field first, so a five-field expression shifts every value by one position. Always count the fields the target platform expects before pasting an expression across.

Why does my */5 cron job overlap or run twice?

Overlaps happen when a single execution takes longer than 5 minutes, so a new run starts before the previous one finishes. Guard against it with a lock file, a database flag, or a tool like flock, and skip the run if the previous instance is still active. Duplicate runs across servers usually mean the same crontab is installed on more than one host — run it on a single node or use a distributed lock.

cronautomationintervalstask schedulingmonitoring