Frequently Asked Questions
You schedule SMS messages using EventBridge by creating a one-time rule with an "at" schedule expression specifying the desired send time in UTC. This rule targets an AWS SNS topic, which then triggers your application's webhook to send the SMS via Vonage. The application uses the AWS SDK to interact with EventBridge and create these scheduled rules.
AWS SNS acts as a decoupling mechanism between the scheduler (EventBridge) and the SMS sending logic. When the scheduled time arrives, EventBridge publishes a message to the designated SNS topic. This message contains the SMS details (phone number, message content), which are then forwarded to your application's webhook for processing and delivery via Vonage. This architecture enhances reliability.
Fastify is a high-performance Node.js web framework chosen for its speed and efficiency. It provides a robust foundation for building the API endpoints needed to handle scheduling requests and process incoming webhook notifications from AWS SNS. Its plugin architecture and schema validation capabilities also contribute to a more organized and maintainable codebase.
Ngrok is beneficial during development and testing when your local Fastify server isn't publicly accessible. Ngrok creates a secure tunnel, providing a public URL that AWS SNS can use to deliver webhook notifications to your locally running server, enabling efficient local development and testing with AWS services.
The provided example demonstrates one-time SMS scheduling using the 'at' expression in EventBridge. For recurring schedules, you'd modify the EventBridge rule to use a 'cron' or 'rate' expression instead of 'at', specifying the desired recurrence pattern. The rest of the architecture (SNS, webhook, Vonage integration) would remain the same.
You'll need a Node.js environment, an AWS account with access to EventBridge and SNS, AWS credentials configured for your application, a Vonage account with a purchased phone number, and a publicly accessible URL for the webhook (ngrok for development, public domain/IP for production). Also, necessary Node packages and AWS resource setup are required.
The application validates the provided 'sendAt' timestamp to ensure it's in the future. If the timestamp is in the past, the scheduling request is rejected with a 400 Bad Request error, preventing attempts to schedule messages for past times.
The PUBLIC_WEBHOOK_URL is essential for AWS SNS to deliver notifications to your Fastify application. It specifies the publicly accessible base URL where your '/webhook/sns' endpoint resides. This URL is used by SNS to send subscription confirmations and notification messages containing SMS details for processing.
Securing the webhook requires verifying the message signature to ensure authenticity and prevent unauthorized requests. This involves verifying the signature against AWS's public key. While not fully implemented in the example, it's crucial for production to confirm the message originates from AWS SNS.
AWS credentials (AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY) are required for the application to interact with AWS services. These can be configured as environment variables or placed in the standard ~/.aws/credentials file. Ensure these credentials have the necessary IAM permissions to manage EventBridge rules, targets, and interact with your SNS topic.
You'll need your Vonage API Key, API Secret, and a Vonage phone number capable of sending SMS. These should be obtained from your Vonage API Dashboard and set in the .env file to allow the application to send SMS messages.
You can use any AWS region that supports SNS and EventBridge. The chosen region should ideally be close to your target audience for lower latency and should be consistent throughout your AWS configuration. Specify your chosen region in the AWS_REGION environment variable.
Build a Production-Ready SMS Scheduler with Fastify, AWS SNS, EventBridge, and Vonage
This guide details how to build a robust SMS scheduling application using Node.js with the Fastify framework, AWS Simple Notification Service (SNS), AWS EventBridge for scheduling, and the Vonage Communications API for sending SMS messages.
You will learn how to create an API endpoint that accepts SMS scheduling requests, leverages AWS services for reliable time-based triggering, and uses Vonage to deliver the messages. This solves the common need for sending timely notifications, reminders, or alerts without maintaining complex internal cron jobs or schedulers.
Project Overview and Goals
Goal: Create a Fastify application with two main API endpoints:
/schedule
: Accepts POST requests to schedule an SMS message for a future time./webhook/sns
: Receives notifications from AWS SNS (triggered by EventBridge) and sends the SMS via Vonage.Problem Solved: Provides a scalable and reliable mechanism for scheduling SMS messages without managing stateful timers or cron jobs within the application itself. Leverages managed cloud services for scheduling and notifications.
Technologies Used:
@vonage/server-sdk
to send SMS messages.System Architecture:
The system follows this flow: A user sends a request to the Fastify
/schedule
endpoint. Fastify creates a one-time rule in AWS EventBridge. At the scheduled time, EventBridge triggers an AWS SNS topic. SNS sends a notification message to the Fastify/webhook/sns
endpoint. Fastify receives the notification, extracts the SMS details, and uses the Vonage API to send the SMS to the end user's phone number.Prerequisites:
~/.aws/credentials
or environment variables). See IAM Permissions section below.ngrok
are excellent for local development and testing.1. Setting up the Project
Let's initialize the project, install dependencies, and set up the basic structure.
1. Create Project Directory:
2. Initialize Node.js Project:
3. Install Dependencies:
Install production dependencies:
Install development dependencies:
fastify
: The web framework.@fastify/env
: For loading and validating environment variables.@aws-sdk/client-eventbridge
: AWS SDK v3 client for EventBridge.@aws-sdk/client-sns
: AWS SDK v3 client for SNS.@vonage/server-sdk
: Vonage Node.js SDK.dotenv
: Loads environment variables from a.env
file for local development.pino-pretty
: (Dev Dependency) Makes Fastify's logs more readable during development.4. Configure
package.json
Scripts:Add the following scripts to your
package.json
for easier development:npm start
: Runs the server normally (suitable for production).npm run dev
: Runs the server with logs piped throughpino-pretty
for better readability during development. Requirespino-pretty
to be installed (as a dev dependency).5. Create Project Structure:
6. Create
.gitignore
:Add
node_modules
and.env
to your.gitignore
file to prevent committing them.7. Setup Environment Variables (
.env
):Create a
.env
file in the project root. Remember to replace placeholders with your actual credentials and ARNs.Explanation of Environment Variables:
AWS_REGION
: The AWS region where your SNS topic and EventBridge rules will reside.SNS_TOPIC_ARN
: The unique identifier for the SNS topic that EventBridge will publish to.EVENTBRIDGE_ROLE_ARN
: The ARN of the IAM role that grants EventBridge permission to publish messages to your SNS topic.VONAGE_API_KEY
,VONAGE_API_SECRET
: Your Vonage API credentials found on the Vonage API Dashboard.VONAGE_FROM_NUMBER
: The Vonage virtual number you purchased, used as the sender ID for SMS messages. Ensure it's in E.164 format (e.g.,+14155552671
). Note: For US numbers, ensure you comply with 10DLC regulations.HOST
,PORT
: Network configuration for the Fastify server.LOG_LEVEL
: Controls the verbosity of logs (info
,debug
,warn
,error
).PUBLIC_WEBHOOK_URL
: The base URL where your/webhook/sns
endpoint is publicly accessible. Crucial for SNS to send notifications.8. Basic Fastify Server Setup (
server.js
):This file initializes Fastify, loads environment variables, registers routes, and starts the server.
This sets up the core server, loads configuration securely, initializes necessary SDK clients, and registers route handlers (which we'll create next).
2. AWS Setup (SNS, EventBridge, IAM)
Before writing the API logic, configure the necessary AWS resources. You can do this via the AWS Management Console or AWS CLI.
1. Create an SNS Topic:
MySmsSchedulerTopic
).SNS_TOPIC_ARN
value in your.env
file.2. Create an IAM Role for EventBridge:
EventBridge needs permission to publish messages to your SNS topic.
<YOUR_SNS_TOPIC_ARN>
with the ARN you copied earlier:EventBridgePublishToMySmsSchedulerTopicPolicy
).MyEventBridgeSnsRole
).EVENTBRIDGE_ROLE_ARN
value in your.env
file.3. Configure IAM Permissions for Your Fastify Application:
The AWS credentials used by your Fastify application (configured via environment variables or
~/.aws/credentials
) need permissions to create EventBridge rules and targets.<YOUR_EVENTBRIDGE_ROLE_ARN>
with the Role ARN from the previous step.iam:PassRole
permission is crucial for allowing EventBridge to assume the role you created.Resource: ""*""
forAllowEventBridgeManageRules
is permissive. In production, it's highly recommended to restrict this to ARNs matching your rule naming convention (e.g.,arn:aws:events:us-east-1:123456789012:rule/sms-schedule-*
) to prevent the application from managing unrelated EventBridge rules.4. Create SNS Subscription (Manual Step Later):
We will create the subscription after the webhook endpoint is running and publicly accessible. SNS needs to send a confirmation request to the endpoint URL.
3. Implementing the Scheduling API (
/schedule
)This endpoint receives the scheduling request and creates the one-time EventBridge rule.
Create
routes/schedule.js
:Explanation:
phoneNumber
_message
_ andsendAt
are provided and correctly formatted (E.164 pattern_ ISO 8601 date).sendAt
time is actually in the future.randomUUID
.at()
schedule expression required by EventBridge for one-time events. Crucially_ this uses UTC time (toISOString
).ruleName
.PutRuleCommand
: Creates the EventBridge rule with the specific schedule time.State: 'ENABLED'
ensures it's active. One-timeat()
schedules are auto-deleted by EventBridge after execution.PutTargetsCommand
: Links the created rule to the SNS Topic ARN specified in the environment variables. It passes thesnsInputPayload
and specifies theEVENTBRIDGE_ROLE_ARN
needed for permissions.202 Accepted
status_ indicating the request was successful and the SMS is scheduled for future delivery.4. Implementing the SNS Webhook Handler (
/webhook/sns
)This endpoint is crucial. It needs to handle two types of incoming POST requests from AWS SNS:
Create
routes/webhook.js
: