Home
/Building a simple reminder service with AWS Lambda
Building a simple reminder service with AWS Lambda
David Kennedy
·
3/24/2024

The following is on overview of how I went about building a simple reminder system for a recent project.

Building a reminder system doesn’t need to be daunting. After researching how other applications handle this, I created a subset of the RRULES (Recurrence Rules) which is part of the iCalendar standard. These rules define pattern of recurrence such as daily, weekly, monthly recurrences.

Since I’m not creating a full calendar application I decided to take a subset of the rules and apply them to the reminder system. The subset included:

  • FREQ: Daily, Weekly

  • INTERVAL: 1, 2 (every other)

  • BYDAY: Monday, Tuesday, Wednesday, etc.

  • BYHOUR: 24 Hrs

  • BYMINUTE: 0, 15, 30, 45

  • TIMEZONE: Set to the users desired timezone

Example Reminder Object
{
  enabled: true,
  frequency: "daily",
  interval: 1,
  byday: "monday",
  byhour: 12,
  byminute: 30,
  tzid: "America/New_York",
  nextReminder: 1715943600000
}

Now we can hook everything up!

A user will select options to determine the value for the rules, and those will be stored as part of the reminder. When a user sets their reminder, I calculate the nextReminder timestamp and save that along with the reminder. This timestamp is stored as milliseconds, allowing me to search for the exact value in the db query, making life a bit easier.

Now for the fun stuff…

AWS Lambdas can be triggered via a CloudWatch schedule, which can go down to every minute. Since I am sending reminders every 15 mins, I set the scheduler to trigger the Lambda to match.

When the lambda is triggered I query the database for reminder which match that 15min period in time. This works because I normalize the timestamp to the 15min no additional seconds or milliseconds.

const now = Date.now();
// Normalize to the closest 15min (12:15:37.1234 => 12:15:00.000 => 1711210500000)
const reminderTS = new Date(now - (now % (15 * 60 * 1000))).getTime();

For the returned reminders I calculate the next reminder based on the recurrence rules described above, save, and send the reminder to the user.

This setup provides a bunch of flexibility. Users can set a new reminder and it the nextReminder is set according to the new rules. No weird queries for upcoming occurrences.

A library which made this super easy is Day.js. A lightweight and extremely useful date library which made it really easy to set nextReminders. See the example below.

// Every day at 12:15PM
const base = dayjs()
  .add(1, "day")
  .hour(12)
  .minute(15)
  .second(0)
  .millisecond(0);

// Set to 12:15PM in users timezone
const nextEventDate = dayjs(base)
  .tz('America/New_York', true);

This was a fun service to build, and I look forward to expanding it in the future.

Hope you enjoyed this overview.

Happy Coding!

Powered by TinyCM