Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
In this article, you use the Azure Developer CLI (azd) to create a Timer trigger function to run a scheduled task in Azure Functions. After verifying the code locally, you deploy it to a new serverless function app you create running in a Flex Consumption plan in Azure Functions.
The project source uses azd to create the function app and related resources and to deploy your code to Azure. This deployment follows current best practices for secure and scalable Azure Functions deployments.
By default, the Flex Consumption plan follows a pay-for-what-you-use billing model, which means you can complete this article and only incur a small cost of a few USD cents or less in your Azure account.
This article supports version 4 of the Node.js programming model for Azure Functions.
This article supports version 2 of the Python programming model for Azure Functions.
Prerequisites
- Java 17 Developer Kit
- If you use another supported version of Java, you must update the project configuration.
- Set the
JAVA_HOMEenvironment variable to the install location of the correct version of the Java Development Kit (JDK).
- Apache Maven 3.8.x
- Node.js 22 or later
- Python 3.11 or later
An Azure account with an active subscription. Create an account for free.
Initialize the project
Use the azd init command to create a local Azure Functions code project from a template.
In your local terminal or command prompt, run this
azd initcommand in an empty folder:azd init --template functions-quickstart-dotnet-azd-timer -e scheduled-dotnetThis command pulls the project files from the template repository and initializes the project in the current folder. The
-eflag sets a name for the current environment. Inazd, the environment maintains a unique deployment context for your app, and you can define more than one. The environment name is also used in the name of the resource group you create in Azure.Run this command to navigate to the app folder:
cd srcCreate a file named local.settings.json in the
srcfolder that contains this JSON data:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", "TIMER_SCHEDULE": "*/30 * * * * *" } }This file is required when running locally.
In your local terminal or command prompt, run this
azd initcommand in an empty folder:azd init --template functions-quickstart-typescript-azd-timer -e scheduled-tsThis command pulls the project files from the template repository and initializes the project in the current folder. The
-eflag sets a name for the current environment. Inazd, the environment maintains a unique deployment context for your app, and you can define more than one. The environment name is also used in the name of the resource group you create in Azure.Create a file named local.settings.json in the
srcfolder that contains this JSON data:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "node", "TIMER_SCHEDULE": "*/30 * * * * *" } }This file is required when running locally.
In your local terminal or command prompt, run this
azd initcommand in an empty folder:azd init --template functions-quickstart-python-azd-timer -e scheduled-pyThis command pulls the project files from the template repository and initializes the project in the current folder. The
-eflag sets a name for the current environment. Inazd, the environment maintains a unique deployment context for your app, and you can define more than one. The environment name is also used in the name of the resource group you create in Azure.Create a file named local.settings.json in the
srcfolder that contains this JSON data:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "python", "TIMER_SCHEDULE": "*/30 * * * * *" } }This file is required when running locally.
Create and activate a virtual environment
In the root folder, run these commands to create and activate a virtual environment named .venv:
python3 -m venv .venv
source .venv/bin/activate
If Python doesn't install the venv package on your Linux distribution, run the following command:
sudo apt-get install python3-venv
In your local terminal or command prompt, run this
azd initcommand in an empty folder:azd init --template functions-quickstart-java-azd-timer -e scheduled-javaThis command pulls the project files from the template repository and initializes the project in the current folder. The
-eflag sets a name for the current environment. Inazd, the environment maintains a unique deployment context for your app, and you can define more than one. The environment name is also used in the name of the resource group you create in Azure.Run this command to navigate to the app folder:
cd srcCreate a file named local.settings.json in the
srcfolder that contains this JSON data:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "java", "TIMER_SCHEDULE": "*/30 * * * * *" } }This file is required when running locally.
In your local terminal or command prompt, run this
azd initcommand in an empty folder:azd init --template functions-quickstart-javascript-azd-timer -e scheduled-jsThis command pulls the project files from the template repository and initializes the project in the current folder. The
-eflag sets a name for the current environment. Inazd, the environment maintains a unique deployment context for your app, and you can define more than one. The environment name is also used in the name of the resource group you create in Azure.Create a file named local.settings.json in the
srcfolder that contains this JSON data:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "node", "TIMER_SCHEDULE": "*/30 * * * * *" } }This file is required when running locally.
In your local terminal or command prompt, run this
azd initcommand in an empty folder:azd init --template functions-quickstart-powershell-azd-timer -e scheduled-psThis command pulls the project files from the template repository and initializes the project in the current folder. The
-eflag sets a name for the current environment. Inazd, the environment maintains a unique deployment context for your app, and you can define more than one. The environment name is also used in the name of the resource group you create in Azure.Run this command to navigate to the app folder:
cd srcCreate a file named local.settings.json in the
srcfolder that contains this JSON data:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "powershell", "TIMER_SCHEDULE": "*/30 * * * * *" } }This file is required when running locally.
Run in your local environment
In a separate terminal window, start the Azurite storage emulator:
azuriteThe local Functions host process uses the Azurite emulator for the internal storage connection (
AzureWebJobsStorage) required by the runtime.
Run this command from your app folder in a terminal or command prompt:
func start
Run this command from your app folder in a terminal or command prompt:
mvn clean package mvn azure-functions:run
Run this command from your app folder in a terminal or command prompt:
npm install func start
Run this command from your app folder in a terminal or command prompt:
npm install npm start
When the Functions host starts in your local project folder, it writes information about your Timer triggered function to the terminal output. You should see your Timer triggered function execute based on the schedule defined in your code.
The default schedule is
*/30 * * * * *, which runs every 30 seconds.When you're done, press Ctrl+C in the terminal window to stop the
func.exehost process.
- Run
deactivateto shut down the virtual environment.
Review the code (optional)
You can review the code that defines the Timer trigger function:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Timer;
using Microsoft.Extensions.Logging;
namespace Company.Function
{
public class timerFunction
{
private readonly ILogger _logger;
public timerFunction(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<timerFunction>();
}
[Function("timerFunction")]
public void Run(
[TimerTrigger("%TIMER_SCHEDULE%", RunOnStartup = true)] TimerInfo myTimer,
FunctionContext context
)
{
_logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
if (myTimer.IsPastDue)
{
_logger.LogWarning("The timer is running late!");
}
}
}
}
You can review the complete template project here.
package com.function;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.annotation.TimerTrigger;
import java.time.LocalDateTime;
/**
* Timer-triggered Azure Function that demonstrates scheduled execution.
*/
public class TimerFunction {
@FunctionName("timerFunction")
public void run(
@TimerTrigger(name = "timerInfo", schedule = "%TIMER_SCHEDULE%") String timerInfo,
final ExecutionContext context) {
context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
if (timerInfo != null && timerInfo.contains("\"isPastDue\":true")) {
context.getLogger().warning("The timer is running late!");
}
}
}
You can review the complete template project here.
const { app } = require('@azure/functions');
async function timerFunction(myTimer, context) {
context.log(`JavaScript Timer trigger function executed at: ${new Date().toISOString()}`);
if (myTimer.isPastDue) {
context.warn("The timer is running late!");
}
}
app.timer('timerFunction', {
schedule: '%TIMER_SCHEDULE%',
runOnStartup: true,
handler: timerFunction,
});
You can review the complete template project here.
import { app, InvocationContext, Timer } from '@azure/functions';
export async function timerFunction(myTimer: Timer, context: InvocationContext): Promise<void> {
context.log(`TypeScript Timer trigger function executed at: ${new Date().toISOString()}`);
if (myTimer.isPastDue) {
context.warn("The timer is running late!");
}
}
app.timer('timerFunction', {
schedule: '%TIMER_SCHEDULE%',
runOnStartup: true,
handler: timerFunction
});
You can review the complete template project here.
# Input bindings are passed in via param block.
param($myTimer)
# Get the current universal time in the default string format.
$currentUTCtime = (Get-Date).ToUniversalTime()
# The 'IsPastDue' property is 'true' when the current function invocation is later than scheduled.
if ($myTimer.IsPastDue) {
Write-Host "PowerShell timer is running late!"
}
# Write an information log with the current time.
Write-Host "PowerShell timer trigger function executed at: $currentUTCtime"
The timer trigger is defined in the corresponding function.json.
You can review the complete template project here.
import datetime
import logging
import azure.functions as func
# Create the function app instance
app = func.FunctionApp()
@app.timer_trigger(schedule="%TIMER_SCHEDULE%",
arg_name="mytimer",
run_on_startup=True,
use_monitor=False)
def timer_function(mytimer: func.TimerRequest) -> None:
utc_timestamp = datetime.datetime.now(datetime.timezone.utc).isoformat()
logging.info(f'Python timer trigger function executed at: {utc_timestamp}')
if mytimer.past_due:
logging.warning('The timer is running late!')
You can review the complete template project here.
Tip
The runOnStartup option is useful during development and testing because the function runs immediately when the host starts. In production, you should set this to false to avoid unexpected executions during deployments or restarts.
After you verify your function locally, it's time to publish it to Azure.
Deploy to Azure
This project uses Bicep files and the azd up command to create a secure deployment to a new function app in a Flex Consumption plan that follows best practices.
Run this command to have
azdcreate the required Azure resources in Azure and deploy your code project to the new function app:azd upThe root folder contains the
azure.yamldefinition file required byazd.If you're not already signed in, you're asked to authenticate with your Azure account.
When prompted, provide these required deployment parameters:
Parameter Description Azure subscription Subscription in which your resources are created. Azure location Azure region in which to create the resource group that contains the new Azure resources. Only regions that currently support the Flex Consumption plan are shown. The
azd upcommand uses your response to these prompts with the Bicep configuration files to complete these deployment tasks:Create and configure these required Azure resources (equivalent to
azd provision):- Flex Consumption plan and function app
- Azure Storage (required) and Application Insights (recommended)
- Access policies and roles for your account
- Service-to-service connections using managed identities (instead of stored connection strings)
- Virtual network to securely run both the function app and the other Azure resources
Package and deploy your code to the deployment container (equivalent to
azd deploy). The app is then started and runs in the deployed package.
After the command completes successfully, you see links to the resources you created.
Verify deployment
After deployment completes, your Timer trigger function automatically starts running in Azure based on its schedule.
In the Azure portal, go to your new function app.
Select Log stream from the left menu to monitor your function executions in real-time.
You should see log entries that show your Timer trigger function executing according to its schedule.
Redeploy your code
Run the azd up command as many times as you need to both provision your Azure resources and deploy code updates to your function app.
Note
Deployed code files are always overwritten by the latest deployment package.
Your initial responses to azd prompts and any environment variables generated by azd are stored locally in your named environment. Use the azd env get-values command to review all of the variables in your environment that were used when creating Azure resources.
Clean up resources
When you're done working with your function app and related resources, use this command to delete the function app and its related resources from Azure and avoid incurring any further costs:
azd down --no-prompt
Note
The --no-prompt option instructs azd to delete your resource group without a confirmation from you.
This command doesn't affect your local code project.