Memory Requirements when Storing JSON from Glance

I'm working on a glance that preloads a JSON file via a web request and caches it in storage for the widget. Since the JSON can be fairly large, I need to implement safeguards to prevent the glance from crashing. If there isn't enough memory available, the glance should simply skip caching the JSON - letting the widget handle the request instead when it's launched.

Handling large JSONs during reception is straightforward: if it's too big, I get a -403 error. But writing to storage seems to be much more memory-intensive. Here, I need to check in advance how much memory is available and try to predict whether storing the JSON will actually succeed.

While experimenting, I noticed something surprising. A modest 3.5kB JSON results in a Dictionary from Communications that consumes over 12kB of memory. Then, to store that Dictionary, I need an additional 24kB of free memory. So in total, that small 3.5kB JSON ends up requiring around 36kB of memory throughout the process.

Have you seen similar behavior in your experience?

  • The Core Topics documentation directly contradicts the API reference. It states:

    "The Application.Storage module manages persistent key-value pair data storage. Information is automatically saved to disk when Storage.setValue() is called. Keys and values are limited to 8 KB each, and a total of 128 KB of storage is available."

    This conflicts with the API reference, which mentions a 32 KB limit per value and notes that the total available storage varies between devices.

    https://developer.garmin.com/connect-iq/core-topics/persisting-data/

    https://developer.garmin.com/connect-iq/api-docs/Toybox/Application/Storage.html

  • Another failed attempt of solving this issue. I wrote a class that decomposes the nested dictionaries that represent the JSON, and writes them into Storage as single Dictionaries, containing links to any sub-dictionaries.

    While the class worked, it just replaced one prolem with another. With this approach I run into Watchdog errors due to too long execution time, even before the memory consumption of Storage.setValue becomes an issue.

    Here’s the class, just for reference:
    DictionaryStorage.mc on GitHub

  • Based on simulator testing, it appears that in a widget, the limit of what can be passed to Storage.setValue is not directly tied to the amount of free memory. Even when switching from an Epix 2 Pro 47mm to a Fenix 6 Pro—which has more available memory—the app still crashes at roughly the same JSON size.

    The following log shows the largest sitemap size that still worked on the Epix 2 Pro 47mm:

    22.5.2025 15:18:53: SitemapStore: used memory = 396,536 B  
    22.5.2025 15:18:53: SitemapStore: total memory = 781,976 B  
    22.5.2025 15:18:53: SitemapStore: free memory = 385,440 B  
    22.5.2025 15:18:53: SitemapStore: estimated sitemap size = 90,944 B  
    

    On the Fenix 6 Pro, the numbers are relatively similar. Despite having more total memory, the maximum working sitemap size is only slightly higher than on the Epix 2 Pro 47mm:

    22.5.2025 15:24:15: SitemapStore: used memory = 507,552 B  
    22.5.2025 15:24:15: SitemapStore: total memory = 1,043,992 B  
    22.5.2025 15:24:15: SitemapStore: free memory = 536,440 B  
    22.5.2025 15:24:15: SitemapStore: estimated sitemap size = 92,784 B  
    
  • Maybe there's some other limit. Like the allocated memory of one object can't be more than some number. 

  • Maybe there's some other limit. Like the allocated memory of one object can't be more than some number. 

    That’s possible, but an Out of Memory error seems like an odd response in this context. The Communications.makeWebRequest API demonstrates how it should be done - it returns a -402 error code when the incoming response is too large to handle.

    In my case, this is actually helpful. The response size that triggers the -402 error is a sensible upper limit for my app. It provides a clear threshold where I can inform the user that their setup is too large. Importantly, this limit is reached well before memory becomes critically low on the supported devices, so it serves as a safeguard against actual Out of Memory errors during UI rendering.

    As for storage, I now write to it only when the in-memory JSON is smaller than 80 kB. This approach works reliably in the simulator across all tested devices, as well as on my own physical device.

    With that in place, it’s now up to the beta testers to push the app to its limits. Until now, they’ve only used relatively small setups.

  • As for the Glance, I’ve decided not to use Storage at all. The potential conflicts and dependencies with other Glance applications make its behavior too unpredictable.