Cron jobs

To run a scheduled job in the cloud, decorate a method with @Cron (or wrap a function in cron()) and give it a schedule. On deploy, each job becomes its own Lambda plus an EventBridge rule on AWS, or a timer-triggered function inside your Function App on Azure. Nothing else runs to keep them alive — no always-on server, no scheduler process.

The same @Cron / cron() code deploys to either provider; see Deploying to Azure for the differences.

Class style — @Cron

Decorate a method with @Cron and give it a schedule:

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

export class Jobs {
  @Cron(rate(5, "minutes"))
  async refreshCache() {
    // …
  }

  @Cron(every("day"))
  async nightlyCleanup() {
    // …
  }

  @Cron({ schedule: "cron(0 12 * * ? *)", id: "daily-report" })
  async sendReport() {
    // …
  }
}

The handler's logical id defaults to ‹Class›-‹method›; pass id to set a stable, explicit name (which also drives the deployed function's name).

Function style — cron()

If you don't use classes, register a standalone exported function with cron():

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

export async function refreshCache() {
  // …
}

cron(rate(5, "minutes"), refreshCache);

The function's name becomes the resource id unless you pass an explicit id:

cron({ schedule: every("hour"), id: "hourly-sync" }, refreshCache);

NestJS

In a Nest app, @Cron goes on a normal provider — with injected dependencies — and you can keep the schedule syntax you already use (a node-cron string or CronExpression). Swapping the import from @nestjs/schedule is usually the only change:

// tasks.service.ts
import { Injectable } from "@nestjs/common";
import { Cron, CronExpression } from "@alzulejos/laranja-decorators";  // ← was @nestjs/schedule

@Injectable()
export class TasksService {
  constructor(private readonly reports: ReportsService) {}   // real DI

  @Cron(CronExpression.EVERY_30_MINUTES)
  async sweep() {
    await this.reports.rebuild();   // `this.reports` is injected
  }
}

Because the method runs on a real provider, laranja resolves it through your app's dependency-injection container instead of new-ing the class. Point it at your module once with the workers() marker:

// src/main.ts (or a dedicated file)
import { workers } from "@alzulejos/laranja-decorators";
import { AppModule } from "./app.module";

export default workers(AppModule);   // build a DI context from this module

Pass AppModule for the whole graph, or a leaner module you compose if you want a smaller cold start. Like the Nest HTTP path, laranja packages your compiled dist/ output — run nest build before deploying so the DI metadata exists.

Schedules

Schedules are written with the portable rate() / every() builders, or as a raw expression string. See the Schedules reference for the full set of options.

@Cron(rate(30, "minutes"))                 // every 30 minutes
@Cron(every("hour"))                       // every hour (shorthand for rate(1, "hour"))
@Cron({ schedule: "cron(0 9 * * ? *)" })   // raw AWS cron: 09:00 UTC daily

Runtime behavior

  • On AWS each cron runs in its own Lambda, isolated from your HTTP app and other jobs; on Azure it's a function in the shared Function App (why).
  • Memory and timeout come from compute, overridable per cron id in resources.
  • All config env and STAGE are available via process.env.