Frequently Asked Questions
You can send bulk SMS messages by creating a RedwoodJS service that interacts with the Plivo API. This service will handle formatting destination numbers and sending the message text via a GraphQL mutation secured with @requireAuth
.
Plivo is a cloud communications platform that provides SMS, voice, and WhatsApp APIs, used in this RedwoodJS application for its robust messaging capabilities and support for bulk sending. It allows you to send messages to multiple recipients with a single API request, reducing latency and simplifying logic.
RedwoodJS offers an integrated full-stack structure, uses GraphQL, and provides developer-friendly features like generators and cells. Its backend services neatly encapsulate business logic like Plivo integration, offering a streamlined development experience for building a bulk SMS feature.
The architecture involves a web frontend sending requests to a RedwoodJS GraphQL API. The API interacts with a RedwoodJS Plivo service, which formats and sends messages via the Plivo API. Optionally, a RedwoodJS database logs messages and handles user interactions.
Create a new RedwoodJS project, install the Plivo Node.js SDK and types in the API workspace, and configure environment variables (PLIVO_AUTH_ID
, PLIVO_AUTH_TOKEN
, PLIVO_SOURCE_NUMBER
) in a .env
file. These credentials are essential for interacting with the Plivo API.
Your Plivo Auth ID and Auth Token can be found on the main dashboard page after logging in to your Plivo Console at https://console.plivo.com/. Plivo documentation provides visual guides to their location on the dashboard if needed.
Your Plivo phone number can be found in the Plivo Console by navigating to Messaging -> Phone Numbers -> Your Numbers. Be sure to select a number enabled for SMS and compliant with country regulations.
Plivo expects destination phone numbers to be concatenated into a single string delimited by the '<' character. For instance, "14155551212<14155551313<14155551414". This allows sending to multiple recipients in one API request.
Secure the endpoint using @requireAuth
directive in the GraphQL schema and set up an authentication provider (like dbAuth, Auth0, Netlify Identity, etc.). Restrict access further using roles (e.g., "admin", "manager") if needed.
While Plivo handles some number variations, validate and normalize numbers into E.164 format (e.g., +14155551212) before sending them to the service to prevent errors. Libraries like libphonenumber-js
are helpful for this purpose.
The sendBulkSms
service function uses try-catch blocks to capture and log errors during Plivo API calls. The function returns a structured response indicating success or failure with error messages. For production, consider more robust retry mechanisms or queueing systems.
Utilize Redwood's built-in Pino logger (src/lib/logger.ts
) to log successful operations (info), failures (error), and detailed information (debug). Configure log levels per environment and consider forwarding logs to dedicated logging services in production.
Initializing the Plivo client outside the sendBulkSms
function allows for potential reuse and avoids recreating the client instance on every call, improving efficiency. It also ensures that environment variables needed for the Plivo client are properly loaded.
Background jobs are recommended for production-level bulk SMS sending, especially for large broadcasts or potential Plivo delays. This decouples sending from the initial request and improves reliability by handling retries and failures independently.
Yes, the example provides an optional logging mechanism using Prisma. A BulkMessageJob
model is added to the Prisma schema, allowing you to store job status, recipient count, messages, errors, and potentially destinations for tracking and analysis.
Build Bulk SMS Broadcasting with Plivo and RedwoodJS: Complete Implementation Guide
This comprehensive tutorial shows you how to implement a production-ready bulk SMS broadcasting system using RedwoodJS and Plivo's SMS API. Whether you're building emergency alert systems, appointment reminders, promotional campaigns, or time-sensitive notifications, this guide covers everything you need to send SMS messages to hundreds or thousands of recipients simultaneously.
You'll learn how to build a secure GraphQL API that processes bulk SMS requests, implement Plivo's bulk messaging API with proper batching (1,000 recipients per request), add authentication and error handling, track delivery status, and deploy to production. This implementation follows RedwoodJS best practices for services, resolvers, and full-stack development.
Prerequisites and RedwoodJS Project Setup for Bulk SMS
Prerequisites:
System requirements: 4 GB RAM minimum, 2 GB free disk space for Node modules and build artifacts.
Plivo pricing consideration: US SMS messages cost approximately $0.0075–$0.01 per message. Test your implementation with small batches before scaling to thousands of recipients.
Create a new RedwoodJS project and install dependencies.
Create RedwoodJS App:
Choose TypeScript when prompted for better type safety.
Navigate to Project Directory:
Install Plivo Node.js SDK: Install Plivo in the
api
workspace only (it's server-side code):Troubleshooting: If installation fails, verify you're in the project root directory and have Node.js v22 LTS installed. Check your network connection – the Plivo SDK downloads native dependencies.
Version pinning: For production, pin specific versions in
api/package.json
(e.g.,"plivo": "4.74.0"
) to ensure consistent builds across environments.Configure Environment Variables: Never hardcode credentials. RedwoodJS uses
.env
files for secure configuration.Create a
.env
file in the project root:Add these variables with your actual Plivo values:
Find your Plivo credentials:
Verify
.env
is in.gitignore
: RedwoodJS adds this by default, but confirm your.env
file is listed to prevent committing secrets.Validate configuration: After setting variables, restart your dev server and check logs for Plivo initialization messages. If credentials are invalid, you'll see error messages when attempting to send.
Team/CI environments: For team development, use environment-specific
.env.development
and.env.test
files (committed with placeholder values). For CI/CD, configure secrets through your platform's environment variable settings (GitHub Actions secrets, GitLab CI/CD variables, etc.).How to Implement the Plivo SMS Service in RedwoodJS
RedwoodJS services encapsulate server-side business logic. Create a service to handle Plivo API interactions.
Generate Messaging Service:
This creates
api/src/services/messaging/messaging.ts
and test files.Implement the Bulk Send Logic: Replace the contents of
api/src/services/messaging/messaging.ts
with this implementation:Key implementation details:
sendBulkSms
Function:'+14155551212<+14155551313<+14155551414'
). Usedestinations.join('<')
.plivoClient.messages.create
with source number_ formatted destination string_ and message texttry...catch
block captures API errors and returns structured responsesDesign Pattern: This Service Layer pattern isolates Plivo interaction logic from GraphQL resolvers_ improving testability and maintainability.
Rate limiting consideration: Plivo enforces account-level rate limits (typically 200–1_000 messages/second depending on your plan). Messages exceeding your rate limit are queued automatically by Plivo_ but expect delays for large batches.
Alternative approach: You could loop through destinations and make individual
messages.create
calls (perhaps usingPromise.all
). However_ this approach is inefficient_ hits API rate limits faster_ and doesn't leverage Plivo's bulk optimization. The '<'-delimited string is Plivo's recommended method for bulk sending.How to Create the GraphQL API for Bulk SMS Broadcasting
RedwoodJS uses GraphQL for its API. Define a mutation to expose the
sendBulkSms
service function.Define GraphQL Schema: Open or create
api/src/graphql/messaging.sdl.ts
and add:Schema details:
BulkSmsResponse
Type: Defines the mutation response structure. GraphQL's type system provides automatic validation and clear client contracts.Mutation
Type: DefinessendBulkMessage
mutation with:destinations
argument: Array of non-null strings (enforced by GraphQL)text
argument: Non-null stringBulkSmsResponse
@requireAuth
: RedwoodJS directive ensuring only authenticated users call this mutation. Add role-based access control if needed.Resolver Mapping (Automatic): RedwoodJS automatically maps the
sendBulkMessage
mutation to thesendBulkSms
function inapi/src/services/messaging/messaging.ts
. No explicit resolver code needed.Testing the Endpoint: Start your RedwoodJS app:
Test using GraphQL Playground at
http://localhost:8911/graphql
or curl.GraphQL Playground test (recommended): Navigate to
http://localhost:8911/graphql
and use this mutation:Variables:
Curl Example: (Requires authentication setup first. For initial testing without auth_ temporarily remove
@requireAuth
from schema)Expected Success Response:
Expected Error Response (e.g._ invalid number):
Plivo SMS API Integration Best Practices for RedwoodJS
The core integration is complete in
messaging.ts
. This section covers additional integration considerations.Configuration Summary
PLIVO_AUTH_ID
andPLIVO_AUTH_TOKEN
stored in.env
_ accessed viaprocess.env
PLIVO_SOURCE_NUMBER
stored in.env
_ used as sender numberSecure Secrets Management
Development:
.env
to version control – verify it's in.gitignore
.env.example
with placeholder values for team collaborationProduction/Deployment:
.env
in deployment bundlesWebhook Integration for Delivery Receipts
To track individual message delivery status_ configure Plivo webhooks:
Add a webhook URL to your message creation call:
Create a webhook handler in RedwoodJS:
Configure the webhook URL in Plivo Console under Messaging → Your Application → Message URL
Fallback Mechanisms
For most applications, retry logic with exponential backoff provides sufficient resilience without added complexity.
Error Handling and Retry Strategies for Bulk SMS Delivery
Robust error handling and logging are essential for production systems.
Error Handling Strategy
Service Level:
try...catch
blocks capture Plivo API errorsBulkSmsResponse
withsuccess: false
and error detailsGraphQL Level:
Common Plivo Error Scenarios:
Authentication failed
Invalid 'dst' parameter
libphonenumber-js
Insufficient balance
Rate limit exceeded
Invalid 'src' parameter
Logging Configuration
Log Levels:
logger.info
: Successful operations, key events (message submitted)logger.error
: Failures, exceptions (API errors)logger.debug
: Detailed information (API responses, formatted numbers)logger.warn
: Potential issues (recipient count exceeding limits)Configure per environment:
Production log forwarding: Forward logs to aggregation services for analysis and alerting:
pino-datadog
transportpino-papertrail
Example configuration:
Retry Mechanisms
Simple Retry with Exponential Backoff:
For transient network errors, implement retry logic:
Background Jobs (Recommended for Scale):
For production systems handling large volumes, decouple SMS sending using background jobs:
Benefits:
Implementation options:
BullMQ example structure:
How to Track SMS Delivery with Database Logging (Optional)
Database logging provides an audit trail for compliance, cost tracking, and debugging.
Privacy and Compliance Considerations
GDPR/Privacy compliance:
Retention policy example:
Define Prisma Schema
Open
api/db/schema.prisma
and add a model for logging:Index strategy:
[status, createdAt]
: Optimizes queries filtering by status with date ranges[createdAt]
: Supports efficient retention policy cleanupApply Migrations
Generate and apply the migration:
Update Service to Log
Modify
api/src/services/messaging/messaging.ts
to write database logs:Performance considerations:
How to Secure Your Bulk SMS API with RedwoodJS Authentication
Security is critical – bulk SMS endpoints can incur costs and enable abuse if exposed.
Authentication Setup
The
@requireAuth
directive in your GraphQL schema provides the first security layer. Configure authentication:Setup dbAuth (self-hosted):
This scaffolds:
Alternative providers:
Follow RedwoodJS Authentication docs for setup instructions.
Verify authentication works:
yarn rw dev
/login
(scaffolded by dbAuth)sendBulkMessage
mutation – should succeed when authenticated, fail when logged outAuthorization (Role-Based Access Control)
Restrict bulk messaging to specific user roles:
Implement roles in User model:
Rate Limiting
Prevent abuse by implementing rate limiting:
Install rate limiting library:
Configure rate limiter:
Input Validation and Sanitization
GraphQL type enforcement: The schema enforces
destinations
as non-null string array andtext
as non-null string.Phone number validation with libphonenumber-js:
Install library:
Add validation to service:
Message length validation:
Frequently Asked Questions About Plivo Bulk SMS with RedwoodJS
How many recipients can I send to in a single Plivo API request?
Plivo supports up to 1,000 unique destination numbers per API request for bulk messaging. For larger lists, split them into batches of 1,000 or fewer. Messages may not deliver instantly – they're queued based on your account's rate limits.
Reference: https://www.plivo.com/docs/messaging/api/message/bulk-messaging
What Node.js version should I use for RedwoodJS and Plivo integration?
Use Node.js v22 LTS for production. Node.js v22 remains in Active LTS until October 2025, then transitions to Maintenance LTS until April 2027. Plivo's Node.js SDK (v4.74.0) supports Node.js 5.5 and higher, making v22 LTS ideal for long-term stability.
How do I format phone numbers for Plivo's bulk SMS API?
Plivo requires E.164 format (e.g.,
+14155551212
). For bulk messaging, separate multiple numbers with the<
character:+14155551212<+14155551313<+14155551414
. Uselibphonenumber-js
to validate and normalize numbers before sending.What are the SMS character limits for Plivo messages?
Character limits depend on encoding:
Plivo automatically detects encoding. GSM-7 covers standard English/Western European characters. UCS-2 handles Unicode (emojis_ special characters). Plivo's intelligent encoding replaces common Unicode characters (smart quotes_ em dashes) with GSM-7 equivalents to optimize costs.
Reference: https://www.plivo.com/docs/messaging/concepts/encoding-and-concatenation
How do I secure my bulk SMS endpoint in RedwoodJS?
Use RedwoodJS's
@requireAuth
directive in your GraphQL schema. For role-based access_ use@requireAuth(roles: ["admin"_ "manager"])
. Configure authentication with dbAuth (self-hosted) or third-party providers (Auth0_ Firebase Auth_ Netlify Identity). Implement rate limiting to prevent abuse. Never expose bulk SMS endpoints without authentication.What is the best way to handle Plivo API errors in RedwoodJS?
Implement comprehensive error handling with
try...catch
blocks in your service layer. Log errors using RedwoodJS's Pino logger (logger.error
). For transient network errors_ implement exponential backoff retry logic (wait 1s_ 2s_ 4s…). For production_ use background job queues (RedwoodJS Jobs or BullMQ + Redis) to decouple sending from GraphQL requests_ preventing timeouts and ensuring delivery during temporary outages.How do I test my bulk SMS implementation without sending real messages?
Development testing approaches:
Plivo test credentials: Plivo provides test credentials that simulate API calls without sending real messages or charging your account. Find these in your Plivo Console under Account Settings → Test Credentials.
Mock testing: For automated tests_ mock the Plivo client using Jest:
GraphQL Playground: Test at
http://localhost:8911/graphql
with sample data (use your own number to verify delivery)Temporary auth bypass: Remove
@requireAuth
during initial testing (remember to add back before deployment)Should I log SMS messages to a database in production?
Database logging is optional but recommended for production:
Benefits:
Implementation: Create a
BulkMessageJob
model storing status (PENDING
,SUBMITTED
,FAILED
), recipient count, Plivo message UUIDs, and error messages.Considerations:
How do I deploy a RedwoodJS bulk SMS application to production?
Deployment platforms:
Deployment checklist:
Environment variables: Configure
PLIVO_AUTH_ID
,PLIVO_AUTH_TOKEN
,PLIVO_SOURCE_NUMBER
through your platform's settings – never commit.env
Database migrations:
Log forwarding: Configure production logging (Datadog, Logtail)
Rate limiting: Implement request throttling for API protection
Message queues: For high volume, deploy BullMQ with Redis or use AWS SQS
Monitoring: Set up alerts for error rates, API costs, delivery failures
CI/CD: Configure GitHub Actions or GitLab CI for automated testing and deployment
Example GitHub Actions workflow:
What are the cost considerations for bulk SMS with Plivo?
Pricing structure:
Cost optimization strategies:
Example cost calculation:
Budget alerts: Set up spending notifications in Plivo Console to prevent unexpected bills.