Frequently Asked Questions
You can schedule reminders in a RedwoodJS application by leveraging AWS EventBridge Scheduler to trigger events at specific times, which then activate a backend process to send notifications via AWS SNS. This setup ensures reliable, scalable scheduling and notification delivery. The reminder details are stored in a PostgreSQL database managed by Prisma, RedwoodJS's ORM.
AWS EventBridge Scheduler is used to trigger the reminder notifications. It acts as a serverless cron job system, reliably executing tasks at scheduled times. This removes the need for managing a separate scheduling infrastructure, simplifying the application's architecture.
AWS SNS provides a scalable and reliable way to send notifications across multiple channels, including email, SMS, and push notifications. Its decoupled nature ensures that notification delivery doesn't impact the core application logic, improving resilience and maintainability.
Prisma is RedwoodJS's default ORM and is used throughout the application lifecycle to interact with the PostgreSQL database. It simplifies database operations by providing a type-safe and convenient way to create, read, update, and delete reminder records.
Create a new project by running the command `yarn create redwood-app redwood-sns-scheduler --typescript --git-init --commit-message 'Initial project setup'`. The `--typescript` flag initializes a TypeScript project, `--git-init` creates a Git repository, and `--commit-message` sets the initial commit message.
The tutorial uses PostgreSQL as the database. It is managed by Prisma, RedwoodJS's built-in Object-Relational Mapper (ORM), enabling easy interaction between the application and the database.
The RedwoodJS application interacts with AWS SNS to send email notifications. The Lambda function, triggered by EventBridge Scheduler, queries the database for due reminders and publishes JSON-formatted messages to an SNS topic. This topic is subscribed to an email endpoint, ensuring delivery to the specified recipient.
The RedwoodJS scheduler uses AWS SNS for sending notifications, EventBridge Scheduler for triggering events, Lambda for running the notification logic, and potentially Secrets Manager for storing database credentials securely. These services provide a serverless architecture for the application.
The Lambda function needs access to the database credentials and permission to publish to the designated SNS topic. An IAM role specifically for the Lambda function is created with these permissions, ensuring secure access to resources.
The status field in the `Reminder` model tracks the reminder's lifecycle, using values like `PENDING`, `SENT`, and `ERROR`. This allows for efficient management and monitoring of the reminder's delivery status.
Storing `scheduledAt` as UTC in the database ensures consistency and avoids timezone-related issues, especially when dealing with users across different geographical locations. This guarantees the reminder is triggered at the correct time regardless of the user's local timezone.
Environment variables are stored in a `.env` file in the project root. This file contains sensitive information like database credentials, AWS access keys, and SNS topic ARNs. For the Lambda function, environment variables are configured through the AWS Lambda console.
You'll need Node.js (v20.x recommended), Yarn (v1.22.21+), an AWS account with necessary permissions, AWS CLI, RedwoodJS CLI, basic Git knowledge, and optionally Docker for local PostgreSQL.
Although not explicitly implemented in the basic tutorial, multi-user support can be added by associating reminders with users in the database schema. This allows filtering reminders based on the current user and enhances data privacy.
This guide provides a comprehensive, step-by-step walkthrough for building a production-ready scheduling and reminder application using RedwoodJS, powered by AWS SNS for notifications and AWS EventBridge Scheduler for triggering events. We'll cover everything from initial setup to deployment and monitoring.
Version: 1.0
Project Overview and Goals
What We're Building:
We will build a RedwoodJS application that enables users to schedule reminders. At the scheduled time, the system will automatically send a notification (e.g., email, SMS) via AWS Simple Notification Service (SNS). The scheduling itself will be managed reliably by AWS EventBridge Scheduler, triggering a backend process to dispatch the reminders.
Problems Solved:
Technologies Used:
System Architecture:
Prerequisites:
nvm
to manage versions.aws configure
).yarn global add redwoodjs-cli
(or usenpx
).Final Outcome:
A functional web application where users can create, view, update, and delete reminders. Scheduled reminders will trigger email notifications (as an example) sent via AWS SNS at the specified time. The system will be robust, scalable, and ready for further feature development.
1. Setting up the Project
Let's initialize our RedwoodJS project and configure the basic environment.
Check Prerequisites:
If Node version is incorrect, use
nvm
:Upgrade Yarn if needed:
npm install --global yarn
Create RedwoodJS App: We'll use TypeScript for better type safety. Use single quotes for the commit message to avoid potential shell issues with nested double quotes.
--typescript
: Initializes the project with TypeScript.--git-init
: Initializes a Git repository.--commit-message
: Sets the initial commit message.yarn install
will likely run automatically if using Yarn v1. If not, runyarn install
.Project Structure Overview:
api/
: Contains the backend code (GraphQL API, services, database schema, functions).web/
: Contains the frontend React code (components, pages, layouts).scripts/
: For utility scripts (like database seeding).redwood.toml
: Project configuration file.package.json
: Project dependencies.Environment Variables (
.env
): Create a.env
file in the project root. This file stores secrets and configuration and should not be committed to Git. Add it to your.gitignore
if it's not already there. IMPORTANT: The values below are placeholders. Replace them with your actual credentials and resource identifiers.DATABASE_URL
connects Prisma to your database. AWS variables allow the SDK to authenticate.SNS_TOPIC_ARN
tells our code which SNS topic to publish to.SCHEDULER_LAMBDA_ARN
might be needed if managing EventBridge from the API side (optional).Database Setup (Local PostgreSQL using Docker): If you have Docker installed, this is the easiest way:
postgres-scheduler
, sets the password, creates the initial database, maps port 5432, and runs it in the background. Ensure the credentials match yourDATABASE_URL
in.env
.Install AWS SDK v3: We'll need the SDK in our API side (potentially) and definitely in our Lambda function later. Let's add it to the API workspace.
2. Creating Database Schema and Data Layer
We need a way to store the reminders.
Define Prisma Schema: Edit
api/db/schema.prisma
. Add aReminder
model.scheduledAt
), the recipient identifier (e.g., email), and a status (PENDING
,SENT
,ERROR
).createdAt
andupdatedAt
are standard timestamp fields.scheduledAt
: Crucially, store this in UTC. Prisma handles JavaScriptDate
objects, which are timezone-aware, but ensure consistency.status
: Tracks the lifecycle of the reminder.recipient
: How we know where to send the notification.@@index
: Creates a database index onscheduledAt
andstatus
. This is vital for the performance of the Lambda function that queries for pending reminders.Apply Database Migrations: Create and apply the database migration using Prisma Migrate.
api/db/migrations/
and applies them to your database defined inDATABASE_URL
. It will also update your Prisma Client.Generate Prisma Client: Migrations usually handle this, but you can run it manually if needed:
(Optional) Seed Sample Data: Create
api/db/seeds.js
to add initial data for testing.Run the seed script:
3. Implementing Core Functionality (Redwood Service)
We need backend logic to manage reminders (Create, Read, Update, Delete). Redwood services are perfect for this.
Generate Reminder Service & SDL: Redwood generators simplify creating the necessary files for a CRUD interface.
api/src/services/reminders/reminders.ts
: Contains functions (resolvers) to interact with theReminder
model.api/src/graphql/reminders.sdl.ts
: Defines the GraphQL schema (types, queries, mutations) for reminders.api/src/directives/requireAuth/requireAuth.ts
andapi/src/directives/skipAuth/skipAuth.ts
(if not already present).api/src/services/reminders/reminders.test.ts
.Review Generated Service (
api/src/services/reminders/reminders.ts
): The generated code provides basic CRUD operations using Prisma.db
).scheduledAt
being in the future withincreateReminder
. Robust validation (e.g._ using Zod) is recommended for production.Review Generated GraphQL SDL (
api/src/graphql/reminders.sdl.ts
): This file defines the API shape.Reminder
type matching the Prisma model.@requireAuth
directive by default. You might change this to@skipAuth
for public access during development or implement actual authentication.Test the API: Start the development server:
Navigate to the GraphQL Playground:
http://localhost:8911/graphql
updateReminder
anddeleteReminder
.4. Setting up AWS Infrastructure (IAM_ SNS_ Lambda_ EventBridge)
This is the core AWS setup for scheduling and notification.
Security First: IAM Setup
We need specific permissions for our different components. Remember to replace placeholders like
YOUR_REGION
_YOUR_ACCOUNT_ID
_ and example resource names with your actual values.IAM User for Local Dev/API (Optional but Recommended):
redwood-scheduler-api-user
(or similar).RedwoodSchedulerAPIPolicy
), and create it..env
file (AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
).IAM Role for Lambda Function: The Lambda function needs permission to access the database (via network/secrets) and publish to SNS.
AWSLambdaBasicExecutionRole
(for CloudWatch Logs).RedwoodSchedulerLambdaSNSPolicy
(or similar), create it.RedwoodSchedulerLambdaSNSPolicy
).RedwoodSchedulerLambdaRole
) and create it. Note the ARN.IAM Role for EventBridge Scheduler: EventBridge needs permission to invoke our Lambda function.
RedwoodEventBridgeInvokeLambdaPolicy
, create it.RedwoodEventBridgeSchedulerRole
) and create it. Note the ARN.SNS Topic Setup
redwood-reminders-topic
.SNS_TOPIC_ARN
value in your.env
file (remembering it's a placeholder there).Confirmed
.Lambda Function Setup
This function will be triggered by EventBridge and will handle sending reminders.
Create Lambda Function Directory: Outside your RedwoodJS project, create a new directory for the Lambda function code. This separates concerns and allows for independent dependency management for the Lambda function.
pg
driver.Copy Prisma Schema and Generate Client: The Lambda needs the schema to generate the correct Prisma client. Copy
schema.prisma
from your Redwood project (api/db/schema.prisma
) into thereminder-scheduler-lambda
directory.--data-proxy
connects through Prisma's managed service, avoiding binary compatibility issues but requiring network access and a Prisma Cloud account setup. Using--binary-targets
requires specifying the exact Linux architecture and OpenSSL version your Lambda runtime uses (check AWS Lambda documentation) and ensuring these binaries are included in your deployment package. The example code below assumesDATABASE_URL
is directly available, but--data-proxy
requires specific connection string format and potentially API key environment variables. Consult Prisma's serverless deployment documentation for details on your chosen strategy. This guide proceeds assuming--data-proxy
for simplicity in the example command, but the code uses a standardDATABASE_URL
.Write Lambda Handler Code (
index.js
):