February 9th, 2026
The Reality + Forecast Hybrid Model Today we implemented a “rapid prototype” of the recurrence engine to visually validate our scheduling architecture. This introduced the concept of merging strict database records (“Reality”) with client-side generated occurrences (“Forecast”) to create a seamless infinite calendar experience.🏎️ Rapid Recurrence Engine
Commit:96b4ea0 proto(tasks): implement rapid recurrence engine for experimentation
We needed a way to visualize recurring tasks without generating millions of database rows upfront. The solution is a hybrid data model:
1. The “Reality” Layer (Database Instances)
- Source: Convex
taskInstancestable. - Represents: Past completed tasks, today’s active tasks, and specific exceptions.
- Mutability: Fully editable, have status (completed/missed), and persistent IDs.
2. The “Forecast” Layer (Virtual Occurrences)
- Source: Generated on the client-side from
tasksrecurrence rules. - Represents: Future instances that haven’t happened yet.
- Mutability: Read-only until interaction converts them into real instances (or until the scheduler creates them just-in-time).
🛠️ Implementation Details
Frontend Logic (useScheduleEvents.ts)
We created a custom hook that merges these two worlds:
Recurrence Utility (recurrence.ts)
Included a pure function generateOccurrences that:
- Takes a task + date range.
- Iterates through days checking
isDayMatch. - Projects
time_windowsonto specific dates. - Returns “virtual” objects compatible with the calendar component.
Backend Updates
- New Index: Added
by_assignee_starttotaskInstancesschema for efficient range querying. - API Endpoint:
list.instancesnow acceptsstartandendtimestamps to support windowed fetching (e.g., “Give me this week’s data”).
📱 User Experience Impact
- Infinite Scrolling: Users can scroll weeks into the future and see their schedule populated instantly.
- Performance: We don’t flood the DB with years of future rows.
- Flexibility: Changing a recurrence rule updates the entire future forecast instantly.