Skip to content

Case List Caching and Lazy Loading in CommCare

Shubham Goyal edited this page Apr 28, 2025 · 2 revisions

Introduction

This document provides an in-depth technical overview of the Case List Caching and Lazy Loading feature implemented in CommCare. It aims to guide developers through the architecture, flow, and technical nuances of the feature, ensuring a clear understanding for future development and maintenance.

Overview of Caching and Lazy Loading

The Case List Caching and Lazy Loading feature in CommCare optimizes case list loading performance by implementing:

  • Lazy Loading: Dynamically loads case properties as the user scrolls, rather than calculating them all upfront.
  • Caching: Stores computed case list properties after the initial load to improve subsequent performance.

These optimizations are particularly beneficial for applications with large case lists or complex case properties that are computationally intensive to calculate.

For a comprehensive guide on enabling and configuring this feature, refer to the Feature Usage Guide: Case List Caching and Lazy Loading in CommCare.

Detail Configuration

Caching and lazy loading can be turned on for a case list detail config by setting the two boolean flags at detail and detail field level as below -

<detail id="m1_case_short" cache_enabled="true" lazy_loading="true">
   <field cache_enabled="true" lazy_loading="true">
   </field>
</detail>

The top level boolean flags provide an indication at the list level whether the list should be optimized while the field level fields define individual fields that should be optimized for the case list.

Flow of Loading a Case List with Caching and Lazy Loading

Understanding the flow of loading a case list with caching and lazy loading is crucial for developers working on this feature. The process can be delineated into several stages:

1. Pre-Loading

Once a user logs into an app, CommCare schedules a background worker to pre-calculate all detail fields backed by cache for all cacheable case lists in the app. This process is normally referred to as cache priming and ensures minimal time spent calculating case list fields when the user navigates to the case list. This process loops over all cacheable case lists and effectively does two things for each of them:

  • Loads the cache for all cacheable case list fields into memory
  • Calculates and subsequently caches any fields that are not already present in the cache

Note that this process happens in the background and is scheduled after the following events:

2. Loading Case List

When the user opens the case list, CommCare performs the following actions to optimally utilize the cache:

  1. Loads the cache for all cacheable case list fields into memory.
  2. Calculates and subsequently caches any fields that are not already present in the cache.
  3. Sorts and displays the case list to the user.
  4. If a property is marked as lazy-loaded, CommCare skips calculating it until it needs to be shown on the case list.

The initial loading of the case list also considers the state of background cache priming work:

  • If background work is in progress and currently priming cache for the current case list:
    Block until background work finishes priming the current case list, then use the result from the background worker to jump directly to step 3 above.

  • If background work is in progress but priming cache for some other case list in the app:
    Cancel the background work and instead load the case list using the steps above inside the current process. After the case list has been loaded, reschedule the background worker to prime the cache for the other case lists.

  • If background work is not in progress:
    Load normally as described in the steps above.

3. Lazy Loading Triggered

  • As the user scrolls down, additional lazy-loaded case properties are fetched and computed on demand.
  • If caching is enabled for the field, the computed values are stored in the cache for future reference.

4. Cache Invalidation

Cached data is invalidated when:

  • A case is updated — cache is invalidated for that case and the tree of all related cases, including transitive relations.
  • A 412 sync occurs — invalidates all cached records.
  • An app update is installed — invalidates all cached records.

Technical Considerations

When implementing or modifying the caching and lazy loading feature, developers should consider the following:

  • Cache Safety:
    Not all XPath calculations are safe to cache, as we currently lack implementations to invalidate caches in response to events that can make cached data stale. These expressions include but are not limited to:

    • External instances except casedb (e.g., Fixtures, CommCareSession instance)
    • Volatile XPath expressions (today(), now(), here(), random(), uuid())
    • Localized outputs
  • Lazy Loading Limitations:
    Lazy-loaded properties cannot be used for sorting or filtering the case list, as they are computed on-demand and may not be available during these operations.

  • Performance Implications:
    While caching improves load times for subsequent accesses, the initial load may take slightly longer due to the overhead of computing and storing cacheable properties.

Clone this wiki locally