Schedules

A schedule tells a cron job when to run. Use the rate() and every() builders — laranja stores them provider-neutrally and lowers them to an EventBridge expression on AWS or NCRONTAB on Azure, so the same code is portable. A raw expression string is available as an escape hatch.

Across providers: on AWS a schedule lowers to an EventBridge expression; on Azure it lowers to NCRONTAB for a timer trigger. The builders are exact either way. One caveat: AWS rate(...) is a fixed interval, while an Azure timer is calendar-aligned — so a rate that doesn't evenly divide its unit (e.g. rate(7, "minutes")) drifts at the unit boundary on Azure, and the deploy warns. Use a divisor (5, 10, 15, 20, 30) to line them up.

rate(value, unit)

"Every N units." Portable everywhere.

import { rate } from "@alzulejos/laranja-decorators";

rate(5, "minutes")   // every 5 minutes
rate(1, "hour")      // every hour
rate(2, "days")      // every 2 days
  • value must be a positive integer (≥ 1).
  • unit is one of "minute", "minutes", "hour", "hours", "day", "days" — singular or plural, your choice.

every(unit)

Shorthand for rate(1, unit). Takes a singular unit:

import { every } from "@alzulejos/laranja-decorators";

every("minute")   // = rate(1, "minute")
every("hour")     // = rate(1, "hour")
every("day")      // = rate(1, "day")

Raw AWS expressions (escape hatch)

When you need something the builders can't express (e.g. "noon UTC every day"), pass a wrapped AWS schedule string — cron(...) or rate(...):

@Cron({ schedule: "cron(0 12 * * ? *)", id: "daily-report" })  // 12:00 UTC daily
@Cron("rate(5 minutes)")                                       // raw rate string

AWS cron has six fields: cron(Minutes Hours Day-of-month Month Day-of-week Year). It's an escape hatch, not an AWS lock-in — on Azure the expression is translated to NCRONTAB for you.

A few examples:

ExpressionMeaning
cron(0 12 * * ? *)12:00 UTC every day
cron(0/15 * * * ? *)every 15 minutes
cron(0 8 ? * MON-FRI *)08:00 UTC on weekdays
cron(0 0 1 * ? *)midnight UTC on the 1st of each month

node-cron expressions (@nestjs/schedule compatibility)

A bare (unwrapped) string is read as a standard 5- or 6-field node-cron expression — the same syntax @nestjs/schedule's @Cron takes. laranja translates it to the AWS dialect for you, so a Nest app can swap the import and keep its existing schedules:

@Cron("0 12 * * *")                 // noon every day
@Cron("*/5 * * * *")                // every 5 minutes
@Cron("0 0 * * 1-5")                // midnight on weekdays
@Cron(CronExpression.EVERY_30_MINUTES)  // the enum works too

CronExpression (mirrored from @nestjs/schedule) is re-exported from @alzulejos/laranja-decorators. Translation handles the day-of-week numbering difference (Unix 0=Sun → AWS 1=Sun) and the day-of-month/day-of-week rule for you.

What can't be translated is rejected at build time — never silently rounded:

InputWhy it's rejected
"*/30 * * * * *", CronExpression.EVERY_30_SECONDSSub-minute — EventBridge's floor is 1 minute.
A seconds field other than 0Second-level offsets can't be expressed.
A cron constraining both day-of-month and day-of-weekEventBridge requires one to be *.

@Interval(ms)

@nestjs/schedule's @Interval is supported and lowers to a rate(...). The interval must be a whole number of minutes (EventBridge's floor):

@Interval(300000)          // every 5 minutes  → rate(5, "minutes")
@Interval("poll", 300000)  // named

@Timeout (a one-shot timer relative to process start) has no serverless equivalent and is rejected with a clear message — use @Cron or @Interval.

Where you can use them

Anywhere a schedule is expected — the decorator or the function marker — accepts a builder result, a Schedule object, or a raw string:

@Cron(rate(5, "minutes"))                       // builder
@Cron("rate(5 minutes)")                        // raw string
@Cron({ schedule: every("day"), id: "nightly" })// builder + explicit id
cron(rate(1, "hour"), refreshCache);            // function marker