AWS EventBridge is a powerful serverless event bus service that makes it easy to connect applications using data from your own applications, integrated Software-as-a-Service (SaaS) applications, and AWS services. One of its key features is the ability to schedule events, allowing you to automate workflows and trigger actions at specific times or intervals.
We recently encountered a scenario where we needed to trigger reminder emails to users for freelancewiz.com and gharsync.com. Since the email reminders had to be sent at specific times, traditional cron jobs would not be the most efficient solution. Instead, we leveraged AWS EventBridge's scheduling capabilities to achieve this.
Sequence Diagram of the Implementation

Let's break down the steps into two main parts: AWS Setup and Application Logic.
AWS Setup
Step 1: Creating an IAM user
- Go to the IAM console in AWS.
- Create a new user with the following policy:
AmazonEventBridgeSchedulerFullAccess - Select the user you just created and navigate to the "Security credentials" tab.
- Create a new access key and note down the Access Key ID and Secret Access Key.
Step 2: Setting up EventBridge Connection
- Go to the EventBridge console in AWS.
- Navigate to "Connections" and create a new connection.
- Choose "API Key" as the authorization type.
- Enter "x-api-key" as the API key name and generate a random API key value (You can generate a secret here Dev Toolkit or use node crypto). You will use this value in your application to authenticate requests.
Step 3: Setting up an API Destination
- In the EventBridge console, navigate to "API destinations" and create a new API destination.
- Provide a name and description for the API destination.
- Enter the endpoint URL of your application where you want to send the scheduled events (e.g.,
https://yourdomain.com/api/reminder). - Select the connection you created in the previous step.
- Set the invocation rate limit as per your requirements.
Step 4: Setting up a Schedule Group
- In the EventBridge console, navigate to "Schedule groups" and create a new schedule group.
- Provide a name and description for the schedule group.
Step 5: Creating an IAM Role for EventBridge
- Go to the IAM console in AWS.
- Create a new role with the custom trust policy that allows EventBridge to assume the role.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": ["events.amazonaws.com", "scheduler.amazonaws.com"]
},
"Action": "sts:AssumeRole"
}
]
}
- Attach the following policy to the role:
AmazonEventBridgeSchedulerFullAccess. - Select the role you just created and add an inline policy. Use the following JSON policy, replacing
<AWS_ACCOUNT_ID>with your actual AWS account ID and the api destination ARN. Your AWS account ID can be found in the top right corner of the AWS Management Console. You can also adjust the region if you're not usingap-south-1.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["events:InvokeApiDestination"],
"Resource": "arn:aws:events:ap-south-1:<AWS_ACCOUNT_ID>:api-destination/my-api-destination/*"
},
{
"Effect": "Allow",
"Action": ["events:RetrieveConnectionCredentials"],
"Resource": "arn:aws:events:ap-south-1:<AWS_ACCOUNT_ID>:connection/*"
},
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:ap-south-1:<AWS_ACCOUNT_ID>:secret:events!connection/*"
},
{
"Effect": "Allow",
"Action": ["events:PutEvents"],
"Resource": "arn:aws:events:ap-south-1:<AWS_ACCOUNT_ID>:event-bus/default"
}
]
}
Step 6: Setting up EventBridge Rule to Invoke API Destination
- In the EventBridge console, navigate to "Rules" and create a new rule.
- Provide a name and description for the rule.
- Set the rule type to "Rule with an event pattern".
- Define the event pattern to match the events you want to trigger the API destination. For example , you can set it to match events with a specific source or detail type.
{
"source": ["fwiz.activity-reminders"],
"detail-type": ["ActivityLogReminder"]
}
- In the "Select targets" section, choose "EventBridge API destination" as the target type.
- Select the API destination you created earlier.
- Choose the role you created in Step 5 for the "Existing role" option.
Application Logic
Step 1: Setting up the API Endpoint
- Create an API endpoint in your application to handle incoming requests from EventBridge. For example, in a NextJS application:
// app/api/reminder/route.ts
import { AWS_EVENTBRIDGE_CONFIG } from "@/lib/vars";
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
export async function POST(request: NextRequest) {
try {
const apiKey = request.headers.get("x-api-key");
// Verify the API key
if (!apiKey || apiKey !== AWS_EVENTBRIDGE_CONFIG.xAPIKey) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
// Parse the request body
const body = await request.json();
const { activityLogId } = body.detail;
if (!activityLogId) {
return NextResponse.json(
{ error: "activityLogId is required" },
{ status: 400 }
);
}
// TODO: Implement your business logic here
// For example:
// - Update the activity log status
// - Send notifications
// - Trigger other workflows
// - Update database records
return NextResponse.json({
success: true,
message: "EventBridge callback processed successfully",
activityLogId: activityLogId,
processedAt: new Date().toISOString(),
});
} catch (error) {
console.error("Error processing EventBridge callback:", error);
if (error instanceof z.ZodError) {
return NextResponse.json(
{
error: "Invalid payload",
details: error.issues,
},
{ status: 400 }
);
}
return NextResponse.json(
{ error: "Internal server error" },
{ status: 500 }
);
}
}
Step 2: Scheduling Events from Your Application
- Use the AWS SDK to schedule events from your application. Here's an example using NextJS:
// lib/eventbridge-scheduler.ts
import {
SchedulerClient,
CreateScheduleCommand,
} from "@aws-sdk/client-scheduler";
import { AWS_EVENTBRIDGE_CONFIG } from "./vars";
const client = new SchedulerClient({
region: AWS_EVENTBRIDGE_CONFIG.region,
credentials: {
accessKeyId: AWS_EVENTBRIDGE_CONFIG.accessKeyId,
secretAccessKey: AWS_EVENTBRIDGE_CONFIG.secretAccessKey,
},
});
interface ScheduleReminderParams {
activityLogId: string;
reminderDate: number;
}
export async function scheduleActivityReminder({
activityLogId,
reminderDate,
}: ScheduleReminderParams) {
try {
// Create a unique schedule name
const scheduleName = `activity-reminder-${activityLogId}`;
// Format the date for EventBridge (must be in future)
const scheduleTime = new Date(reminderDate).toISOString();
const command = new CreateScheduleCommand({
Name: scheduleName,
GroupName: "fwiz-activity-reminders",
Description: `Reminder for activity log ${activityLogId}`,
// One-time schedule at specific date/time
ScheduleExpression: `at(${scheduleTime.slice(0, 19)})`,
ScheduleExpressionTimezone: "UTC",
// Flexible time window (required for one-time schedules)
FlexibleTimeWindow: {
Mode: "OFF",
},
// The target configuration
Target: {
Arn: "arn:aws:scheduler:::aws-sdk:eventbridge:putEvents",
RoleArn: AWS_EVENTBRIDGE_CONFIG.roleArn,
Input: JSON.stringify({
Entries: [
{
Source: "fwiz.activity-reminders",
DetailType: "ActivityLogReminder",
Detail: JSON.stringify({
activityLogId: activityLogId, // Add any other relevant details here
}),
EventBusName: "default",
},
],
}),
RetryPolicy: {
MaximumRetryAttempts: 3,
MaximumEventAgeInSeconds: 3600, // 1 hour
},
},
// Delete the schedule after it executes
ActionAfterCompletion: "DELETE",
});
const response = await client.send(command);
console.log(`Schedule created: ${response.ScheduleArn}`);
return {
success: true,
scheduleArn: response.ScheduleArn,
scheduleName: scheduleName,
};
} catch (error) {
console.error("Error creating schedule:", error);
throw error;
}
}
Ensure you have the following environment variables set in your application:
AWS_EVENTBRIDGE_CONFIG.region- The AWS region where your EventBridge resources are located.AWS_EVENTBRIDGE_CONFIG.accessKeyId- The Access Key ID of the IAM user you created.AWS_EVENTBRIDGE_CONFIG.secretAccessKey- The Secret Access Key of the IAM user you created.AWS_EVENTBRIDGE_CONFIG.roleArn- The ARN of the IAM role you created for EventBridge.
Conclusion
AWS EventBridge's scheduling capabilities provide a robust alternative to traditional cron jobs, especially when you need to trigger events at specific times across distributed systems.
The setup might seem involved initially, but once configured, managing scheduled events becomes straightforward. You get built-in retry mechanisms, monitoring through CloudWatch, and the flexibility to handle complex scheduling patterns that would be challenging with conventional approaches.
One thing to keep in mind is that the IAM policies we've outlined here can be adjusted based on your specific security requirements and use cases. You might want to be more restrictive with permissions or add additional resources depending on your infrastructure setup.
If you found this tutorial helpful or have suggestions for improvements, feel free to reach out to us at contact@madishtech.com. We'd love to hear about your experiences implementing EventBridge scheduling or any questions you might have about automating workflows with AWS services.