Practical KaiOS Optimization Tips

Posted by Tom Barrasso on

Practical KaiOS Optimization Tips

Lessons. Here are a few tips I learned first hand developing PodLP for KaiOS smart feature phones.


What’s Memoization? It’s basically a form of caching, eliminating repetitive calculation and repeated function calls by storing results in memory.

How to memoize? There are many JavaScript libraries like moize that can wrap functions for automatic memoization, or you can do it youself.

PodLP Using Podcast Accent Color
PodLP Using Podcast Accent Color

Image Processing: in PodLP, the header background color is set to match the accent color of the podcast thumbnail. Computing this value is expensive, and it doesn’t change often (only when the image itself changes), so it’s faster to cache the value rather than recompute it.

 1const colorMap = new Map();
 3function getAccentColor(imageBlob) {
 4    const imageHash = hash(imageBlob);
 6    // First time: compute the accent color
 7    if (!colorMap.has(imageHash)) {
 8        colorMap.set(imageHash, computeAccentColor(imageBlob));
 9    }
11    return colorMap.get(imageHash);

In the example above, it would be better to persist the computed color in data storage like localStorage to avoid recomputing the next time the app is opened. Better still: compute values like this server-side (which is how PodLP actually does it).

Watch out for asynchronous functions, or functions that return a Promise. These need to be handled differently, always wrapping the immediately-returned cached value with Promise.resolve, and keeping track of in-flight Promises.

Remote Requests: you might memoize the boolean return value for whether a given host is unresolveable because of the Let’s Encrypt (LE) SSL Certificate issue. There are easy ways to memoize Promises too.

Keep it small. KaiOS devices have 256-512mb of RAM, and much of that is reserved for the OS itself. Because memoized return values are stored in memory, it works especially well where the serialized input and output of computation is small (i.e. a color or boolean).

Instant Click

Background. Our prior guide on KaiOS optimization covered prefetch hints. We can extend this concept further using the preconnect keyword, similar to InstantClick.

In this overly-simplified example, the user presses the Enter key to select the next page in a single-page app (SPA). Subsequently, this page will make a fetch or XMLHttpRequest call to load a remote resource.

 1function preconnect(url) {
 2    let link = document.createElement('link');
 3    link.rel = 'preconnect';
 4    link.href = url;
 5    document.head.appendChild(link);
 8window.onkeydown = (event) => {
 9    if (event.key === 'Enter') {
10        preconnect(''); // Instant Click
12        // Loads new elements and triggered Fetch to
13        //
14        loadNextPage();
15    }

Impact. Preconnecting provides a hint to the browser that can noticeably reduce the time to establish a connection to an origin. This can effectively parallelize connection time with render time, decreasing effective load time by 100s of milliseconds.

Loading Indicators. Although it’s best practice to minimize animations on KaiOS, well-optimized animations can be useful, especially as a distraction while something is loading. Skeleton loading placeholders are a good example.

⚠️ Warning: only preconnect to a few critical-path origins, as preconnecting to too many can be counterproductive. Use dns-prefetch for less critical resources.

Image Cache & Resize

TLDR. Use a free and open-source like to generate only-the-fly thumbnails for KaiOS.


  • It’s dual-stack (IPv4/IPv6), so it worked on IPv6-only networks like India’s Reliance Jio
  • It’s hosted on Cloudflare, so you won’t run into the expired LE root certificate issue
  • It has parameters to control image format (output=png), so you can render previously-unsupported formats like AVIF and WebP (KaiOS 2.5 supports neither)
  • It has parameters to control size (w=150&h=150), so images can be scaled down to fit KaiOS (and use less memory)
  • It’s free and open source

Alternatively, Cloudflare Image Optimization is another off-the-shelf solution, or you can always downsize and compress images ahead of time.

Podcast artwork tends to be between 1400x1400 to 3000x3000 pixels in size. While this makes sense for high-resolution smartphones, it’s a waste downloading all those pixels just to render on a 240x320 screen. PodLP generates thumbnails server-side, but for those that fail for a variety of reasons, the fallback is to proxy via

(Maybe) Don’t Use ServiceWorkers

Background. ServiceWorkers are background Workers that proxy all HTTP requests via the fetch event, cache Request/ Response pairs, and they’re required to handle push notifications. ServiceWorkers can enable offline experiences and reduce page load times, in conjunction with the Caches API.

However, there is overhead to starting a service worker and passing all requests through even a no-op listener. In my experience, doing so can add a few hundred milliseconds round-trip to each request.

Push Notifications on KaiOS
Push Notifications on KaiOS

When to use ServiceWorkers

  • For Web Push Notifications (it’s required)
  • Queueing requests until connection reestablishes
  • Background processing computationally-expensive tasks (i.e. encryption)
  • Handling System Messages on KaiOS 3.0

KaiOS Version Differences

  • Permission: On KaiOS 2.5, the serviceworker permission is required to expose the navigator.serviceWorker and install your worker. This permission was removed on KaiOS 3.0
  • On KaiOS 2.5, you can install a ServiceWorker without a fetch handler. However, on KaiOS 3.0 you must set a fetch handler in order for your worker to be installable


KaiOS devices come with many technical constraints, from limited memory and persisted storage, slower network speeds (no 5G) and small screen sizes. Building performant and usable applications requires numerous changes and performance profiling on a range of commercial devices. If you need an experienced partner to build a top-notch KaiOS experience for your business, contact the author from the About page.