Scheduling Tasks with CloudWatch and .NET Lambda


A common use case when working with AWS Lambda and .NET is running code on a schedule, similar to a cron job. AWS makes this easy with Amazon CloudWatch Events (now part of Amazon EventBridge), allowing you to repeatedly trigger Lambda functions.
In this post, we’ll walk through how to schedule a .NET Lambda function using CloudWatch and how to structure your code for maintainability.
Prerequisites
Before you begin, make sure you have the following:
An AWS Account with permission to create Lambda functions and CloudWatch rules
The .NET SDK is installed (preferably .NET 6 or later)
The AWS CLI is installed and configured (
aws configure
)Amazon.Lambda.Tools installed via the .NET CLI:
dotnet tool install -g Amazon.Lambda.Tools
Basic familiarity with AWS Lambda and the .NET CLI
Step 1: Create the .NET Lambda Function
You can use the AWS-provided templates with the Amazon.Lambda.Templates
package.
dotnet new lambda.EmptyFunction --name ScheduledTaskLambda
cd ScheduledTaskLambda
Edit the Function.cs
file:
public class Function
{
public async Task FunctionHandler(ILambdaContext context)
{
context.Logger.LogLine("Scheduled task triggered at: " + DateTime.UtcNow);
// Your logic here
await DoScheduledWork();
}
private Task DoScheduledWork()
{
// Simulate a task like cleanup, email reminder, or sync
Console.WriteLine("Running scheduled task...");
return Task.CompletedTask;
}
}
Step 2: Deploy the Lambda Function
Deploy the Lambda:
dotnet lambda deploy-function ScheduledTaskLambda
You’ll be prompted for AWS credentials and region during the deployment.
Step 3: Schedule with CloudWatch Event Rule
You can use the AWS Console or the AWS CLI:
aws events put-rule \
--schedule-expression "rate(5 minutes)" \
--name MyScheduledLambdaRule
Add the Lambda target:
aws events put-targets \
--rule MyScheduledLambdaRule \
--targets "Id"="1","Arn"="arn:aws:lambda:<region>:<account-id>:function:ScheduledTaskLambda"
Grant CloudWatch permission to invoke the Lambda:
aws lambda add-permission \
--function-name ScheduledTaskLambda \
--statement-id MyScheduledEventPermission \
--action 'lambda:InvokeFunction' \
--principal events.amazonaws.com \
--source-arn arn:aws:events:<region>:<account-id>:rule/MyScheduledLambdaRule
Using Cron Expressions
Instead of rate()
You can use cron expressions:
--schedule-expression "cron(0 12 * * ? *)"
This triggers at 12:00 PM UTC every day. AWS cron format:
cron(Minutes Hours Day-of-month Month Day-of-week Year)
Real-World Example: Sending a Daily Email Report
Let’s say your system collects usage metrics or user activity throughout the day. Every morning at 8 AM UTC, you want to email a summary report to your team. You’ll:
Query a database or analytics source
Generate a report, either plain text or HTML
Send the report using Amazon SES or another email provider
This is a great use case for a scheduled Lambda function.
Example Code
public class Function
{
public async Task FunctionHandler(ILambdaContext context)
{
var report = await GenerateReport();
await SendEmail(report);
context.Logger.LogLine("Daily report sent at: " + DateTime.UtcNow);
}
private Task<string> GenerateReport()
{
// Query a DB or metrics API. Simulated output:
return Task.FromResult("User signups: 42\nErrors: 3\nSales: $1280");
}
private Task SendEmail(string report)
{
// Integrate with Amazon SES, SendGrid, or another provider
Console.WriteLine("Sending email with report:\n" + report);
return Task.CompletedTask;
}
}
This Lambda can be scheduled using the following cron expression:
bashCopy code--schedule-expression "cron(0 8 * * ? *)"
This means 8:00 AM UTC every day.
Logging and Monitoring
View logs in CloudWatch Logs
Add custom logging using
context.Logger.LogLine(...)
Use structured logging libraries like Serilog for better insights
Summary
With just a few commands and a bit of .NET code, you can schedule tasks using CloudWatch Events and AWS Lambda. This approach is scalable, cost-effective, and fully serverless.
Benefits Recap:
No server maintenance
Pay only for executions
Integrated with the AWS ecosystem
Ideal for recurring jobs like cleanup, reporting, data sync, and reminders
References
Subscribe to my newsletter
Read articles from Renato Ramos Nascimento directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Renato Ramos Nascimento
Renato Ramos Nascimento
With over 14 years in software development, I specialize in backend systems using .NET, Python, and Java. I bring full lifecycle expertise, including requirements analysis, client/server and data layer development, automated testing (unit, integration, end-to-end), and CI/CD implementations using Docker, GitLab Pipelines, GitHub Actions, Terraform, and AWS CodeStar.