intermediate 12 min read

How to Set Up Cron Jobs with Azure Functions (Timer Trigger)

Learn how to create scheduled Azure Functions using Timer Triggers with NCRONTAB expressions. Covers setup, testing, monitoring, and production deployment.

Prerequisites

  • Azure account
  • Azure Functions Core Tools
  • Node.js 18+ or .NET 8+

What Are Timer Triggers?

Azure Functions Timer Triggers run your function on a schedule defined by an NCRONTAB expression. NCRONTAB is a 6-field cron format that includes seconds, similar to Quartz cron.

Timer Triggers are serverless — you don't manage any infrastructure. Azure handles scaling, retries, and execution. You only pay for execution time.

Quick Start

Create a Timer Trigger function:

bash
func new --name TimerTask --template "Timer trigger"

JavaScript/TypeScript example:

typescript
// src/functions/timerTask.ts
import { app, InvocationContext, Timer } from '@azure/functions';

app.timer('timerTask', {
  schedule: '0 */5 * * * *',  // Every 5 minutes
  handler: async (timer: Timer, context: InvocationContext) => {
    context.log('Timer function ran at', new Date().toISOString());

    if (timer.isPastDue) {
      context.log('Timer is past due!');
    }

    await processQueue();
  },
});

C# example:

csharp
[Function("TimerTask")]
public void Run(
    [TimerTrigger("0 */5 * * * *")] TimerInfo timer,
    FunctionContext context)
{
    context.Logger.LogInformation($"Timer ran at: {DateTime.Now}");
    if (timer.IsPastDue) context.Logger.LogWarning("Timer is past due!");
}

NCRONTAB Expression Syntax

Azure uses NCRONTAB — a 6-field format with seconds:

second minute hour day-of-month month day-of-week

Examples:

  • 0 */5 * * * * — Every 5 minutes
  • 0 0 * * * * — Every hour
  • 0 0 9 * * 1-5 — Weekdays at 9 AM
  • 0 0 0 1 * * — First day of every month
  • 0 30 9 * * * — Daily at 9:30 AM

The first field is seconds. If you only provide 5 fields, Azure treats it as standard cron (no seconds).

Common NCRONTAB Expressions

  • 0 */5 * * * * — Every 5 minutes
  • 0 0 * * * * — Every hour
  • 0 0 0 * * * — Daily at midnight
  • 0 0 9 * * 1-5 — Weekdays at 9 AM
  • 0 0 0 1 * * — First day of every month
  • 0 0 */6 * * * — Every 6 hours
  • 0 0 12 * * * — Every day at noon

Every weekday at 9:00 AM

Next runs (UTC):

Mon, May 18, 2026 09:00

Tue, May 19, 2026 09:00

Wed, May 20, 2026 09:00

Local Development

Run locally with Azure Functions Core Tools:

bash
npm install -g azure-functions-core-tools@4
func start

Timer triggers run on schedule even locally. To test immediately, send a POST to the admin endpoint:

bash
curl -X POST http://localhost:7071/admin/functions/timerTask -H "Content-Type: application/json" -d '{}'

Timezone configuration in host.json:

json
{
  "extensions": {
    "timers": {
      "defaultTimezone": "Eastern Standard Time"
    }
  }
}

Uses Windows timezone names. On Linux consumption plan, use IANA names like America/New_York.

Monitoring with Application Insights

Azure Functions integrates with Application Insights for monitoring:

  • Invocation count — verify your timer is firing
  • Duration — track execution time
  • Failures — alert on errors
typescript
app.timer('timerTask', {
  schedule: '0 */5 * * * *',
  handler: async (timer, context) => {
    const start = Date.now();
    try {
      await processQueue();
      context.log(`Completed in ${Date.now() - start}ms`);
    } catch (error) {
      context.error('Timer task failed:', error);
      throw error; // Rethrow so Azure marks it as failed
    }
  },
});

Set up alerts in Azure Monitor for function failures or high duration.

Production Tips

Handle past-due timers: When your function app scales from zero, timers that were missed during the cold start will fire with isPastDue = true. Decide whether to process or skip them.

Singleton lock: By default, timer triggers use a blob lease to ensure only one instance runs at a time across all scaled instances. This is handled automatically.

App Settings: Store the schedule in an app setting for easy changes:

typescript
app.timer('timerTask', {
  schedule: '%TimerSchedule%',  // Reads from app settings
  handler: async (timer, context) => { ... },
});

Then set TimerSchedule = 0 */5 * * * * in your Function App's Configuration.

Frequently Asked Questions