Skip to main content

February 11th, 2026

The Great Refactor: Why Client-Side Merging is Unsustainable Today marks a critical realization point in our architecture. We identified a fundamental pain point in our current “lazy materialization” strategy that makes frontend development exponentially harder.

🧐 The Curiosity Question

“When we go to the calendar, if we need to show the next instance, we need to combine past instances, and for the future we need to use the recurrence logic to render virtual events for which instances haven’t been formed yet, then merge them, and then look after edge cases… and it becomes hectic. Am I right?”
The answer is a resounding YES.

🧩 The Current Architecture

Our current flow is optimized for database efficiency but creates massive complexity for the UI.
  1. Task Creation: final.tsxcreate.tsservice.ts
  2. Scheduling: scheduler.ts creates ONLY the next instance.
  3. Chain Logic: It schedules a check at the end of that instance to create the subsequent one.

The Problem: “The Calendar View”

To render a simple calendar, the frontend currently has to perform a high-wire act:
  1. Fetch Real Instances: Query the DB for what exists (past + current).
  2. Fetch Recurrence Rules: Get the abstract definitions (RRULE, days, times).
  3. Generate Virtual Events: Run complex date logic on the client to project future slots.
  4. Merge & Deduplicate: Combine real rows with virtual objects, ensuring no overlaps at the “now” boundary.
  5. Handle Edge Cases:
    • What if a user completed a task early?
    • What if a task was skipped?
    • What about timezones?
    • What about infinite scrolling?

💥 Why It’s “Hectic” - The Technical Breakdown

The current “lazy materialization” approach forces the frontend to handle logic that belongs in the backend:

1. Two Sources of Truth

We are forced to reconcile two completely different data structures for the exact same timeline:
  • Database Rows (Materialized Instances) -> “What happened”
  • Recurrence Rules (Virtual Objects) -> “What should happen”

2. The “Boundary” Problem

The most fragile part is the “seam” where real instances end and virtual ones begin.
  • Off-by-one errors: Is the next slot covered by a pending instance or is it virtual?
  • Timezone hell: Recurrence rules effectively “float” while instances are fixed in UTC.
  • Status conflicts: If a task was skipped yesterday, does the rule know to skip it or will it regenerate it?

3. Duplication of Logic

Every single consumer of calendar data must re-implement this complex merge logic:
  • The Schedule View needs it.
  • The List View needs it.
  • The Home Widget needs it.
  • Notification Helpers need it.

4. Testing Nightmares

To verify if the calendar works, we can’t just mock a DB response. We have to:
  • Simulate a DB state with specific gaps.
  • Simulate the client-side clock.
  • Verify the merge logic produced the correct seamless list.

🚀 The Pivot Point

We are acknowledging that while lazy materialization saves DB space, it shifts an unacceptable amount of complexity to the client. We are essentially re-implementing the scheduler in React just to render a view. This realization sets the stage for a major refactor: moving the source of truth back to a unified model.
Next Steps: We need a design that simplifies data fetching so the frontend can just “render events” without performing complex temporal calculus.