← Blog

RRULE Explained: How Recurring Reminders Actually Work

July 21, 2026 · 6 min read

RRULE is the recurrence-rule format defined in RFC 5545, the same specification behind the iCalendar format used by Google Calendar, Apple Calendar, and Outlook. If you've ever set a calendar event to repeat "every 2nd Tuesday," you've used RRULE without seeing the syntax.

Why not just store "repeat every N days"?

It works until it doesn't. A few cases where a naive interval breaks down:

  • "Every month on the 31st" — most months don't have one. Do you skip, or fall back to the last day of the month?
  • "Every weekday" — a plain interval can't express "not weekends" at all.
  • Daylight saving time — "every 24 hours" silently drifts by an hour twice a year if you're not tracking wall-clock time correctly.
  • "The last Friday of every month" — no fixed interval expresses this; it has to be a rule, not a delta.

The basic shape of an RRULE string

A rule is a semicolon-separated set of key=value pairs. The two you'll use most:

FREQ=DAILY
FREQ=WEEKLY
FREQ=MONTHLY
FREQ=YEARLY

FREQ sets the base unit. From there, you narrow it down. "Every Monday" adds a day-of-week filter:

FREQ=WEEKLY;BYDAY=MO

Multiple days works the same way — "every Monday, Wednesday, and Friday":

FREQ=WEEKLY;BYDAY=MO,WE,FR

"The 15th of every month":

FREQ=MONTHLY;BYMONTHDAY=15

And "the last Friday of every month" — the pattern a plain interval genuinely cannot express:

FREQ=MONTHLY;BYDAY=FR;BYSETPOS=-1

How this shows up in a reminders app

When a recurring reminder gets delivered, the system needs to compute the next valid occurrence from the rule, not just add a fixed offset to the current due date. That's the actual job an RRULE engine does: given "FREQ=MONTHLY;BYDAY=FR;BYSETPOS=-1" and today's date, work out the next date that satisfies the rule, correctly, across month boundaries, leap years, and DST changes.

Reminders.md exposes simple presets (daily, weekly, monthly) in the dashboard for the common cases, and accepts full RRULE strings via the API and MCP for anything more specific — "every weekday," "the first of the month," "every other Tuesday" — without needing a UI built for every possible pattern.

The takeaway

If a recurring task in some app has ever silently skipped a month or landed on the wrong day, the underlying cause is almost always a naive interval standing in for something that needed an actual rule. RRULE exists specifically because "add N days" stops being correct the moment a human describes a schedule in human terms.