Announcing Schedules API

Today we’re excited to announce our schedules API, a flexible, declarative way to build recurring notifications, without having to manage cron jobs in your own codebase.

With the Knock schedules API, you can create personalized rules for your users, synchronize those schedules to Knock, and let our scalable notification infrastructure handle the execution of the notification workflows, with no cron infrastructure required on your end. Schedules are recipient time zone aware and have a declarative model for defining when they should repeat.

Schedules are available today across all Knock plans. You can read on to learn more or get started in our documentation.

Why we introduced scheduled notifications

Scheduled and recurring notifications are a great way to keep your users updated about the flow of work and activity happening in your product. A few common use cases:

  • Weekly or daily notification digests of notifications received
  • Recurring daily summaries for events scheduled for that day
  • A one-off scheduled notification to notify about system maintenance

However, introducing scheduled notifications into your system usually means introducing cron jobs and the associated infrastructure to support running those cron tasks. These crons start simple but quickly grow in complexity as you start to support multiple scheduled notification types, per-customer and user preferences on digest frequencies, and per-user timezone support. Additionally, because notifications are a critical path for users, the reliable execution of the cron jobs becomes a priority for the engineering teams operating the system.

In the past, teams using Knock to power their scheduled notifications have still needed to absorb some of this complexity by triggering their Knock workflows from scheduled cron tasks. With our schedules API, those teams can offload this entire burden to Knock and deliver a more tailored experience to their users.

A flexible but powerful scheduling API

At Knock, we believe in separation of concerns and in encapsulating concepts as primitives that can be composed through APIs. Our schedules API applies these principles to bring our customers a flexible and powerful API that can express any notification schedule, customizable per recipient.

Each schedule created represents when a particular notification workflow should run for a recipient, and defines when the scheduled workflow should repeat.

You can think of a schedule as a managed, recipient-timezone-aware cron job that Knock will run on your behalf.

Because schedules trigger Knock workflows, you can use the same powerful notification building blocks to create sophisticated, cross-channel notifications.

How schedules work

Once a schedule is created and synchronized to Knock, the Knock notification engine will execute the workflow at the given schedule. On completion of the workflow, the next occurrence will be scheduled for the recipient according to the repeat rules defined.

await knock.workflows.createSchedules("daily-reminder", {
	recipients: ["chris", "sam"],
	repeats: [{ frequency: "daily" }],
	scheduled_at: tomorrow,
});

Each schedule created is scoped per-recipient, making it possible to create completely different schedules per recipient in a given workflow. That means in the example above that it’s possible to have a schedule that runs once a week for chris but runs daily for sam.

Defining complex repeat rules for a schedule

We based our schedules format around the iCalendar events specification, a well-established specification for defining recurring events. This specification allows us to represent complex rules such as:

  • Run every other Monday at 6.30pm.
  • Run on the first Tuesday of every month.
  • Run every Wednesday at 4pm and every Thursday at 3pm.

We’re big proponents of building on top of established standards rather than reinventing the wheel, and are glad to have found the iCal events specification while exploring this problem space.

You can see more examples of modeling complex repeat rules in our documentation.

Designed to scale

Building a notification system that executes a recurring schedule to send tens or hundreds of thousands of concurrent notifications is no easy feat. Scaling that system as your user base grows is even more challenging, with more infrastructure and optimizations required to ensure the timely and reliable execution of your notifications.

Fortunately, schedules are built using the same scalable infrastructure that Knock is built on, making it possible to execute schedules concurrently for hundreds of thousands or millions of recipients. Behind-the-scenes Knock ensures each scheduled notification is delivered, taking into account the rate limits for the end provider and handling retry logic as needed.

Knock scales with you as your user base grows without you needing to introduce complex cron or message queue infrastructure to support your growing notification volume. You can even get visibility into your scheduled notifications through our observability features.

Timezone aware, no date math required

Engineers dread working with dates and times, and for good reason, date math is a foot gun waiting to happen. When we set out to design schedules, we knew that any solution wouldn’t be complete without adding timezone support. Today we’re also introducing first-class support for recipient timezones in Knock.

Let’s see what this looks like in practice to create a schedule that executes every day at 7 am in the recipient’s timezone:

// Chris is in 🇬🇧 and Sam is in 🗽
await knock.users.identify("chris", { timezone: "Europe/London" });
await knock.users.identify("sam", { timezone: "America/New_York" });

// Send a wake-up call at 7 am every day in their timezone
await knock.workflows.createSchedules("wakeup-call", {
  recipients: ["chris", "sam"],
	repeats: [{ frequency: "daily", hours: 7 }],
});

You’ll notice here that all of the complexity is taken care of for you behind the scenes: you never have to think about date math or casting schedules in a particular timezone. You can just express the business rule and Knock will handle the rest.

Schedules are also timezone changing aware, so if chris moves from London to New York, then we can simply update his timezone to America/New_York and all of the schedules will be adjusted accordingly. It all just works.

Visibility via the Knock dashboard

Like all features in Knock, schedules can be viewed and debugged from the Knock dashboard. From the dashboard you can see:

  • All schedules for a given recipient, as well as when that schedule will next execute and what the repeat rules are.
  • All recipients who have schedules for a given workflow, as well as when that schedule will next execute and what the repeat rules are.
  • Any workflow runs that were triggered from a schedule, with the ability to debug those runs via the workflow run viewer.

Additionally, with the new per recipient timezone support we’ve added a new popover that will show you information about when a workflow executed relative to your current timezone. We’re big fans of never doing timezone math here at Knock HQ.

The Knock timezone helper

Get started with schedules

Schedules, including timezone-aware schedule support, are available across all Knock plans.

You can get started by reading the documentation or by following our guide on building recurring notifications.