CronNestJS

Cron Syntax Guide: Expressions, Fields, and NestJS Examples

Understand 5-field and 6-field cron, common symbols, NestJS examples, time zones, and the scheduling mistakes caused by missing seconds or UTC assumptions.

·Updated ·10 min·Counting...
Cron Syntax Guide: Expressions, Fields, and NestJS Examples

What Is Cron? A Practical Guide to This Time Language

"Clean the database every day at 2 AM", "sync the cache every 15 minutes", "send a report every Monday at 8 AM" - behind all of these automation tasks there is one quiet but powerful piece: Cron.


1. What is Cron?

Cron is an expression language used to describe when a task should run. It does not execute the task itself. It only defines the schedule, and a scheduler triggers your code when the expression matches.

You can think of it as a DSL for time.


2. Why should you understand Cron?

  • Scheduled cleanup, data archiving, report generation, cache refreshes, and external sync jobs all rely on it.
  • Modern frameworks such as NestJS, Spring, and Django, along with cloud platforms like Kubernetes and Serverless systems, commonly support Cron.

In NestJS, one line is enough to define a scheduled task:

import { Cron } from '@nestjs/schedule';

@Cron('0 0 2 * * *', { timeZone: 'UTC' })
handleCron() {
  console.log('Runs every day at 2 AM');
}

3. The two common Cron formats

1) Standard Unix format (5 fields)

minute hour day month weekday

Example:

0 2 * * *

Meaning: run every day at 02

.


2) Extended format (6 fields, used by NestJS)

second minute hour day month weekday

Example:

0 0 2 * * *

Meaning: run every day at 02:00

.

NestJS expects 6 fields.
If you pass 5 fields, the expression can be parsed with the wrong positions and the timing becomes incorrect.


4. Field layout for the 6-field format

┌──────────── second (0–59)
│ ┌────────── minute (0–59)
│ │ ┌──────── hour (0–23)
│ │ │ ┌────── day (1–31)
│ │ │ │ ┌──── month (1–12)
│ │ │ │ │ ┌── weekday (0–7, where 0/7 = Sunday)
│ │ │ │ │ │
0  0  2  *  *  *   -> runs every day at 02:00:00

5. Quick syntax reference

Symbol Meaning Example
* any value * * * * * * -> every second
, multiple values 0 0 8,20 * * * -> 8 AM and 8 PM
- range 0 0 9-17 * * 1-5 -> weekdays, every hour from 9 to 17
/ step value 0 */15 * * * * -> every 15 minutes

6. Common 6-field expressions

Expression Meaning Run time
0 0 2 * * * every day at 2 AM 02:00
0 30 3 * * * every day at 3
AM
03:30
0 0 */6 * * * every 6 hours 00
, 06
, 12
, 18
0 0 8 * * 1-5 8 AM on weekdays Monday to Friday, 08:00
0 0 0 1 1 * every New Year's Day 01-01 00:00
0 */15 * * * * every 15 minutes minute 00, 15, 30, 45

7. A good NestJS pattern

1) Put schedule values in environment variables

# .env.production
CLEANUP_ENABLED=true
CLEANUP_CRON="0 0 2 * * *"
CLEANUP_TIMEZONE=UTC

2) Centralize them in a config object

export class RateLimitConfig {
  static readonly CLEANUP = {
    ENABLED: process.env.CLEANUP_ENABLED === 'true',
    CRON: process.env.CLEANUP_CRON || '0 0 2 * * *',
    TIMEZONE: process.env.CLEANUP_TIMEZONE || 'UTC',
  };
}

3) Register the job in a service

@Cron(RateLimitConfig.CLEANUP.CRON, {
  name: 'cleanup-job',
  timeZone: RateLimitConfig.CLEANUP.TIMEZONE,
})
async cleanup() {
  if (!RateLimitConfig.CLEANUP.ENABLED) return;
  // your cleanup logic...
}

8. Common mistakes

Mistake Problem Better version
0 2 * * * 5 fields can be misread in NestJS "0 0 2 * * *"
0 0 2 * * * without quotes the shell can split on spaces in some contexts "0 0 2 * * *"
no timezone specified behavior changes across different servers timeZone: 'UTC' or 'Asia/Shanghai'

9. Time zones

  • Cron uses the system time zone by default. In cloud and container environments that often means UTC.
  • A practical rule: use Asia/Shanghai while developing locally if that matches your time zone, and use UTC in production for consistency.
@Cron('0 0 2 * * *', { timeZone: 'Asia/Shanghai' })
Time zone Meaning
UTC Coordinated Universal Time, often best for production
Asia/Shanghai China Standard Time, UTC+8
America/New_York Eastern Time
Europe/London London Time

10. Validation and debugging

Local validation

npm i cron-parser
import * as parser from 'cron-parser';

const it = parser.parseExpression('0 0 2 * * *');
console.log('Next 5 runs:');
for (let i = 0; i < 5; i++) console.log(it.next().toString());

Online tools


11. A simple timeline example

Timeline example for 0 0 2 * * *:
00:00 ------------+------------+------------+------------
                    ^
                    +-- 02:00:00 every day

12. Production checklist

Before shipping a scheduled job, check more than the expression itself:

  1. Time zone: decide whether the job follows local business time or UTC. Reports for humans often use a local time zone; cleanup jobs often use UTC.
  2. Idempotency: make the job safe to run twice. Retries, redeploys, or multiple workers can otherwise create duplicate reports or repeated cleanup.
  3. Overlap: decide what happens if one run is still active when the next run starts. Long imports and API syncs need locking or a skip strategy.
  4. Observability: log job start, job end, duration, and important counts. A cron job that fails quietly is worse than no cron job.
  5. Manual replay: document how to run the same logic manually for recovery. The schedule should trigger the work; it should not be the only way to invoke it.

For NestJS, keep the scheduled method thin. Let it call a service method that can also be tested and run manually. That keeps the cron decorator focused on timing and the business logic focused on the task.

13. Choosing a schedule

Use the least surprising schedule that meets the requirement. “Every five minutes” is easy to write but can be noisy if the job calls third-party APIs. “At 2 AM” is simple until your servers run in UTC and your users expect local time. “Every weekday” needs a decision about holidays.

When in doubt, start with a conservative interval, measure duration and failure rate, then tighten the schedule only if the business need is clear.

Cron is best for predictable time-based work. If the task depends on external events, a queue, webhook, or explicit user action may be a cleaner trigger than a schedule that keeps checking whether something happened.

The most common production mistake is not the syntax itself. It is forgetting whether your runtime expects 5 fields or 6, and forgetting which timezone the server is actually using.

If you are also working in NestJS, pair this with NestJS decorators: class vs method decorators, because scheduled jobs and decorators often appear in the same backend codebase.


12. Where does Cron fit conceptually?

Domain: job scheduling and system automation.
Stack position: backend infrastructure, somewhere between application logic and system operations.
Relation to databases: it often triggers database backup, cleanup, or archive jobs, but Cron itself is not a database technology.

A simple mental map:

Software Engineering
 ├─ Backend
 │   ├─ Web frameworks (NestJS, Spring)
 │   ├─ Job queues (BullMQ, Celery)
 │   └─ Scheduled tasks (Cron / @nestjs/schedule)  <-
 ├─ System Operations
 │   ├─ Process management (pm2, systemd)
 │   └─ Cron daemon (crond)  <-
 └─ Database Administration

Subscribe to FreeMac

Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.