Frequently Asked Questions
Use Node.js with Express, PostgreSQL, Prisma, node-cron, and the Infobip SMS API to build a robust reminder service. This setup allows you to store reminder details in a database, schedule sending times, and reliably deliver SMS messages via Infobip's platform.
Node-cron is a task scheduler in Node.js that allows you to automate tasks. In an SMS reminder service, it's used to trigger the sending of SMS messages at specified times, ensuring reminders are delivered promptly.
Storing reminder times in UTC (Coordinated Universal Time) prevents timezone issues. This ensures that reminders are sent at the correct time regardless of the user's location or server settings.
Express-rate-limit helps protect your API from abuse, such as brute-force attacks. It limits the number of requests an IP address can make within a time window, enhancing the security and stability of your application.
Yes, a free Infobip trial account can be used for testing. Keep in mind there are limitations, such as restrictions on recipient numbers. For production, a paid account is necessary for full functionality and higher message volumes.
Initialize the Infobip Node.js SDK with your API key and base URL. These credentials can be found in your Infobip account dashboard. Ensure the URL includes "https://" and error handle for missing configurations.
Set up a cron job using node-cron's schedule method. Define the desired schedule (e.g., every minute, daily, etc.) and the function to send reminders. Use UTC timezone to avoid time discrepancies.
Prisma simplifies database interactions in Node.js. It's an ORM (Object-Relational Mapper) that allows you to define your database schema and access data using JavaScript objects, making database operations more efficient and type-safe.
Create directories for config, controllers, routes, services, and utils within a src folder. This structure improves code organization, maintainability, and separation of concerns.
PostgreSQL is recommended for its reliability and efficiency. It's a powerful open-source relational database suitable for handling large volumes of reminder data and frequent queries.
You'll need Node.js, access to a PostgreSQL database, an Infobip account, basic familiarity with Node.js, Express, REST APIs, and databases, and tools like cURL or Postman for testing.
Use the libphonenumber-js library in your Node.js project. This library helps validate and format phone numbers according to international standards, ensuring that you're using correct number formats for SMS delivery.
Storing phone numbers in E.164 format (+15551234567) is recommended for consistency and compatibility. The format ensures correct number parsing and avoids issues with different regional formats.
Winston provides flexible logging for your application. It helps you track events, errors, and other relevant information, aiding in debugging and monitoring the health of your service.
Automated reminders are a powerful tool for user engagement, reducing no-shows, and improving communication. Whether it's for appointments, upcoming payments, subscription renewals, or event notifications, sending timely SMS reminders can significantly enhance user experience and operational efficiency.
This guide provides a step-by-step walkthrough for building a robust SMS reminder service using Node.js, Express, PostgreSQL (with Prisma for ORM),
node-cron
for scheduling, and the Infobip SMS API for message delivery. We'll cover everything from project setup and core logic to error handling, security, deployment, and monitoring, enabling you to build a reliable, production-grade application.Project Goals:
Technologies Used:
node-cron
: A simple cron-like task scheduler for Node.js.dotenv
: To manage environment variables securely.express-validator
: For robust API request validation.winston
: For flexible logging.express-rate-limit
: To protect the API against brute-force attacks.Prerequisites:
curl
or a tool like Postman for testing the API.System Architecture:
A diagram here would illustrate the flow: Client interacts with the Node.js API, which uses PostgreSQL for storage and the Scheduler. The Scheduler queries the database and triggers SMS sending via the Infobip API.
1. Setting up the Project
Let's start by initializing our Node.js project, installing dependencies, and setting up the basic structure.
1. Initialize Project:
2. Install Core Dependencies:
express
: Web framework.dotenv
: Loads environment variables from a.env
file.@infobip-api/sdk
: The official Infobip Node.js SDK.node-cron
: Task scheduler.prisma
,@prisma/client
: ORM and database client.pg
: PostgreSQL driver for Node.js (used by Prisma).winston
: Logger.express-validator
: Request validation middleware.express-rate-limit
: API rate limiting.libphonenumber-js
: Robust phone number parsing and validation.3. Install Development Dependencies:
nodemon
: Automatically restarts the server during development.typescript
and@types/*
: For optional TypeScript support and type definitions. Even if writing JavaScript, types help with SDK usage and editor integration.jest
,@types/jest
: Testing framework.supertest
: For integration testing API endpoints.4. Initialize Prisma:
This command creates:
prisma
directory with aschema.prisma
file (for defining your database schema)..env
file (if it doesn't exist) with a placeholderDATABASE_URL
.5. Configure
.env
:Open the
.env
file and configure your database connection string and add placeholders for Infobip credentials.DATABASE_URL
: Replaceuser
,password
,localhost
,5432
, andreminders_db
with your actual PostgreSQL credentials and database name. Ensure the database exists.INFOBIP_BASE_URL
: Find this in your Infobip account under API Keys. It's specific to your account. Ensure it includes the scheme (https://
).INFOBIP_API_KEY
: Generate an API key in your Infobip account dashboard.INFOBIP_SENDER_ID
: The 'From' name displayed on the SMS. Availability depends on regulations.InfoSMS
is a common default.6. Define Database Schema (
prisma/schema.prisma
):Replace the contents of
prisma/schema.prisma
with the following schema for our reminders:Reminder
model with necessary fields.reminderTime
is crucial and should always be stored in UTC to avoid time zone issues.status
tracks whether the reminder has been processed.reminderTime
andstatus
significantly speeds up queries performed by the scheduler.+15551234567
) is recommended for storingrecipientPhoneNumber
for consistency.7. Apply Database Migrations:
Run the following command to create the
Reminder
table in your database based on the schema:This command will:
prisma/migrations
.@prisma/client
) based on your schema.8. Project Structure:
Organize your code for better maintainability. Create a
src
directory:Create these directories:
mkdir -p src/config src/controllers src/routes src/services src/utils
9. Basic Server Setup (
src/server.js
andsrc/app.js
):src/server.js
: Entry point to start the server.src/app.js
: Express application configuration.10. Configure Logger (
src/config/logger.js
):11. Add Run Scripts (
package.json
):Add scripts to your
package.json
for convenience:Now you can run
npm run dev
to start the server with automatic restarts,npm start
to run it normally, andnpm test
to run tests (once configured).2. Implementing Core Functionality (Scheduling & SMS Sending)
This is the heart of the service. We'll set up the Infobip client, create a service to send SMS, and build the scheduler to check for due reminders.
1. Configure Infobip Client (
src/config/infobipClient.js
):.env
.http
before passing it to the SDK.2. Create SMS Sending Service (
src/services/smsService.js
):infobipClient
.libphonenumber-js
to attempt parsing and formatting the number to the digit-only international format Infobip usually expects (e.g.,44...
from+44...
). Includes basic fallbacks but throws an error if formatting fails.messageId
which is crucial for debugging.3. Implement the Scheduler (
src/services/schedulerService.js
):node-cron
to schedulecheckAndSendReminders
to run every minute (* * * * *
). Important: The cron job itself runs based on UTC (timezone: ""UTC""
) because our database times are in UTC.taskRunning
lock to prevent the job from running concurrently if the previous run takes longer than a minute.reminderTime
falls within this window. Crucially, this comparison works correctly because bothreminderTime
in the DB and thenow
/oneMinuteAgo
variables are in UTC.sendSms
.SENT
on success.FAILED
on error. Includes error handling for the status update itself. (Retry logic placeholders added).initializeScheduler
function is exported to be called fromserver.js
after the server starts.3. Building the API Layer
We need endpoints to create, view, and potentially delete reminders.
1. Define Validation Rules (
src/utils/validators.js
):express-validator
for clear and reusable validation logic.libphonenumber-js
for robust phone number validation. Enforces valid format. Includes an optional commented line to normalize to E.164.recipientPhoneNumber
,message
(increased length limit, Infobip handles multi-part), andreminderTime
(must be strict ISO8601 format with timezone and in the future).handleValidationErrors
to return formatted errors.2. Create Reminder Controller (
src/controllers/reminderController.js
):