· ai-devtools

Article: Offline-First AI Coding Tutor for Low-End Android Phones Addresses Storage, Quota, Cold Start

A year spent observing students fade from an academy showed a pattern: they would join live classes, participate actively, and then vanish mid-session.


Most did not intentionally leave; their connections simply could not sustain a lesson. Out of eighty enrolled students, only six managed to graduate.

This experience exposed four deeply ingrained assumptions within coding education platforms: the learner possesses a laptop, has broadband access, reads English proficiently, or belongs to an institution with existing resources. The platform developed, Efiwe, actively subverts all these premises. It operates within a smartphone browser, functions offline after a singular setup, executes code submitted by learners locally, and requires no data bundle post-initial load.

The core focus of this engineering deep-dive is not pedagogical quality, but rather the systems that failed. The true challenges in this domain involve storage limitations, data quotas, cold start performance, and designing robust failure paths. These issues extend far beyond education, applying to any product catering to users on constrained hardware with sporadic network access.

The initial decision favored a Progressive Web App over a native Android application for three key reasons. First, an APK download consumes a data bundle, creating install friction for users rationing data. A PWA allows learning to begin immediately, incrementally caching data in the background. Second, continuous updates are possible via service worker propagation, circumventing the delay inherent in store releases.

The third factor was achieving a unified runtime for code execution—Python, SQL, JavaScript, and HTML—without relying on a server. WebAssembly provided this cross-platform capability. While a native shell wrapping a WebView was considered, it would still suffer from the initial APK download friction, which was unacceptable for a product designed to remove starting barriers.

Executing code locally is essential, especially in environments like a classroom in Ijebu-Ode, Nigeria, where unreliable connectivity makes server round-trips impractical for iterative challenge attempts. For SQL, sql.js (SQLite compiled to WebAssembly) is used; for Python, Pyodide (CPython compiled to WebAssembly) is employed.

To manage the inherent slowness of these runtimes, the guiding principle became that no runtime should initialize on the main thread, and initialization must be deferred until necessary. Course selection triggers a lazy worker spin-up, ensuring the challenge screen's first paint never waits on the setup process.

Managing cached translations across 246 languages presented a significant storage hurdle. Initially, localStorage was used, but it proved insufficient for two reasons. First, its capacity ceiling, roughly 5MB, was easily breached by multi-language course content, causing `QuotaExceededError` on write. Second, its synchronous nature caused visible main-thread stalls on low-powered Android devices during startup reads.

The solution involved migrating to IndexedDB, which offers asynchronous operation and a quota based on available disk space. Migrating existing users proved complex; a dual-read window was implemented to safely transition data from the legacy synchronous store to the new IndexedDB, ensuring no cached translations or in-progress states were lost during the transition.

Related coverage

Also worth reading

  1. next.js 16.5.0-canary.35 released
  2. next.js 16.5.0-canary.33 released
  3. angular 22.2.4 released
  4. LibreOffice's 'no AI' stance meets LLM-assisted code
  5. “Urgency is an inherently subjective call”: Anthropic tells TNS how it grades Claude Duet