<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Kahiether 🌬️ Stories 🏕️]]></title><description><![CDATA[ ✨Some innovations emerge from the toughest conditions. Progress begins when open tools empower everyone, everywhere.✨]]></description><link>https://kahiether.com/</link><image><url>https://kahiether.com/favicon.png</url><title>Kahiether 🌬️ Stories 🏕️</title><link>https://kahiether.com/</link></image><generator>Ghost 5.78</generator><lastBuildDate>Mon, 04 May 2026 09:27:21 GMT</lastBuildDate><atom:link href="https://kahiether.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA["Serving a clear single purpose " ⚗️  Kahiether services]]></title><description><![CDATA[<h2 id="innovating-is-a-journey%F0%9F%9B%A3%EF%B8%8F">Innovating is a journey&#x1F6E3;&#xFE0F;</h2><p>The journey of Kahiether is not about chasing the latest framework or achieving peak performance benchmarks. It is about creating a microservice and an ecosystem that remains simple, portable, flexible, and above all, useful in everyday life. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" class="kg-image" alt="person standing across water during sunset" loading="lazy" width="3000" height="2000" srcset="https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Photo by </span><a href="https://unsplash.com/@geoffroyh?ref=kahiether.com"><span style="white-space: pre-wrap;">Geoffroy Hauwen</span></a><span style="white-space: pre-wrap;"> / </span><a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"><span style="white-space: pre-wrap;">Unsplash</span></a></figcaption></figure><p>Over more</p>]]></description><link>https://kahiether.com/serving-a-clear-single-purpose-kahiether-microservice/</link><guid isPermaLink="false">68b6f141e67cd500013eb59a</guid><dc:creator><![CDATA[敏 Ранд 🧭]]></dc:creator><pubDate>Fri, 05 Sep 2025 21:11:54 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1556231603-01537f2777d6?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDU3fHxqb3VybmV5fGVufDB8fHx8MTc1NzEwNjc5MHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<h2 id="innovating-is-a-journey%F0%9F%9B%A3%EF%B8%8F">Innovating is a journey&#x1F6E3;&#xFE0F;</h2><img src="https://images.unsplash.com/photo-1556231603-01537f2777d6?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDU3fHxqb3VybmV5fGVufDB8fHx8MTc1NzEwNjc5MHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="&quot;Serving a clear single purpose &quot; &#x2697;&#xFE0F;  Kahiether services"><p>The journey of Kahiether is not about chasing the latest framework or achieving peak performance benchmarks. It is about creating a microservice and an ecosystem that remains simple, portable, flexible, and above all, useful in everyday life. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" class="kg-image" alt="&quot;Serving a clear single purpose &quot; &#x2697;&#xFE0F;  Kahiether services" loading="lazy" width="3000" height="2000" srcset="https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1523028212154-f90d1b1fd434?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDYxfHxqb3VybmV5fGVufDB8fHx8MTc1NjgyMTc1NHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Photo by </span><a href="https://unsplash.com/@geoffroyh?ref=kahiether.com"><span style="white-space: pre-wrap;">Geoffroy Hauwen</span></a><span style="white-space: pre-wrap;"> / </span><a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"><span style="white-space: pre-wrap;">Unsplash</span></a></figcaption></figure><p>Over more than a decade  of trials , false starts, and accumulated experience, a vision emerged: to design something minimal yet practical, something resilient yet lightweight, something that does not bend under the weight of complexity.</p><p>In my sleep I dreamed one time of a world where automated systems could assist people, so everyone could keep their job will less hours, spending more time with family, doing with activities and doing what they really want to do.</p><p>Kahiether&apos;s Microservice is not engineered as a system designed for the market. It began as an exploration of how tools could be built to just assist and reduce workload. </p><p>The process involves identifying recurring difficulties, learning from repeated failures, forming a clear vision, and then gradually building the foundations of an ecosystem that grows one service at a time.  We learned in  production engineering concepts that are the essence of improvement: </p><ul><li>&#x6539;&#x5584; (Kaizen) : Improve Continuously</li><li>&#x5E73;&#x6E96;&#x5316; (Heijunka) : Level production / load</li><li>&#x7121;&#x99C4; (Muda) : Eliminate waste</li><li>&#x6A19;&#x6E96;&#x4F5C;&#x696D; (Hyojun sagyo) : Standardize work</li><li>&#x73FE;&#x5730;&#x73FE;&#x7269; (Genchi Genbutsu) : Check directly in production to see real problems</li><li>The 5 S :<ul><li> &#x6574;&#x7406;  : sort &quot;most used vs less used&quot;</li><li>&#x6574;&#x9813; : organize &quot; easy to find&quot;</li><li>&#x6E05;&#x6383; : clean &quot; start fresh &quot;</li><li>&#x6E05;&#x6F54; : standardize &quot;create patterns and architectures&quot;</li><li>&#x8EBE; : discipline &quot; follow as possible the vision&quot;</li></ul></li></ul><p>The result of transposing these process into software engineering create a frame to build a microservice, but this process was not linear and simple as expected.</p><hr><h2 id="constraints-before-kahiether-%F0%9F%8C%8B">Constraints Before Kahiether &#x1F30B;</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1599775656303-14fa38cbbdf4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI2fHx2b2xjYW5vJTIwaXNsYW5kfGVufDB8fHx8MTc1NjgyMTgwOHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" class="kg-image" alt="&quot;Serving a clear single purpose &quot; &#x2697;&#xFE0F;  Kahiether services" loading="lazy" width="6000" height="4000" srcset="https://images.unsplash.com/photo-1599775656303-14fa38cbbdf4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI2fHx2b2xjYW5vJTIwaXNsYW5kfGVufDB8fHx8MTc1NjgyMTgwOHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1599775656303-14fa38cbbdf4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI2fHx2b2xjYW5vJTIwaXNsYW5kfGVufDB8fHx8MTc1NjgyMTgwOHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1599775656303-14fa38cbbdf4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI2fHx2b2xjYW5vJTIwaXNsYW5kfGVufDB8fHx8MTc1NjgyMTgwOHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1599775656303-14fa38cbbdf4?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDI2fHx2b2xjYW5vJTIwaXNsYW5kfGVufDB8fHx8MTc1NjgyMTgwOHww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Photo by </span><a href="https://unsplash.com/@rfsa?ref=kahiether.com"><span style="white-space: pre-wrap;">Rui Amaro</span></a><span style="white-space: pre-wrap;"> / </span><a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"><span style="white-space: pre-wrap;">Unsplash</span></a></figcaption></figure><blockquote>Large applications often suffer from a fundamental overwork: only a fraction of the code is used at all.</blockquote><p>In many systems, around 80 percent of the logic remains dormant, running only in rare cases or existing to support optional features. For example, a software must be compatible and run in CentOS, Feodora, Debian, Windows 11 but at some point of its lifecycle no one use Debian to run it. Yet this unused code still needs to be maintained, updated, and shipped. It increases complexity without adding proportional value. Such bloat leads to applications that are heavier than they need to be, with consequences for performance, maintainability, and scalability.</p><blockquote>A second difficulty arises in the imbalance of component usage.</blockquote><p> In many platforms, different parts of the application receive drastically different amounts of traffic, I particularly noticed this in e-commerce and markeplace applications. For example, a product page might account for half of the total system load (in RAM, CPU, thread and disk memory for data), while a cart handles ten percent and other sections much less. Despite these uneven demands, traditional architectures scale the entire application uniformly. This creates inefficiency, as resources must be allocated to every component even when only one or two are under stress. The result is unnecessary cost and complexity.</p><blockquote>We (buy and) install modules because we don&apos;t want to rewrite what was already written before, but these modules in most of cases contains a lot of parts that doesn&apos;t fit to our use case and opens the way to customization mess.</blockquote><p>Indeed, another source of frustration comes from libraries ( dear npm/yarn install&#x1F604;). Many libraries are designed for broad compatibility: multiple operating systems, numerous use cases, and features covering edge scenarios. Yet in practice, less than half of the library&#x2019;s code is ever called by the application. The rest is unused, but it still ships, loads, and needs maintenance. Instead of simplifying work, such libraries often add hidden layers of complexity.  </p><p>Taken together, these constraints revealed a problem : mainstream approaches are all different and they were not aligned with personal needs of simplicity, efficiency, and autonomy. These problems set the stage for the search for a different approach.</p><hr><h2 id="improving-from-failures-%E2%9B%BA">Improving from Failures &#x26FA;</h2><p>The first attempt to solve these difficulties was an application called MyPa, short for &#x201C;My Personal Assistant.&#x201D; It was created in <a rel="noopener">VBA</a>, and its purpose was straightforward: to store data, open links, and act as an assistant. I included inside a monolithic structure with hyperlink storage and opening, data management, data mass import and quick manipulation Although it worked at a basic level, it was constrained by the environment. </p><blockquote>VBA tied the tool and restricted web and mobile capabilities.</blockquote><p> It was an experiment that highlighted the things not to do and paved the way to the exploration of numerous open-source microservices available online, mostly built in JavaScript.  Each attempt revealed once again that the existing options were designed with assumptions that did not align with the goals at hand.</p><blockquote>A more ambitious step was then taken: building a microservice directly using <a rel="noopener">Vue.js 2</a>.</blockquote><p> At first, it seemed promising.  Tools like <a rel="noopener">Webpack</a> were added to manage builds, followed later by <a rel="noopener">Vite</a>. Each of these technologies is really powerful, state-of-the-art but their introduction came with trade-offs: performance improvements at the cost of rising technical debt, maintenance work, number of dependencies. Instead of reducing complexity, these tools expanded it.CSS libraries were also brought in to simplify interface work. While they offered shortcuts, they introduced the same long-term issue: dependency overhead.</p><blockquote> A small project could quickly become entangled in third-party code that added weight without proportional utility. Over time, these dependencies made the project harder to maintain.</blockquote><p>These failures stretched over a certain time. Each attempt reached a certain point and then collapsed under the same contradictions: seeking simplicity while being trapped by complexity. Yet from these failures, clarity emerged. The accumulated lessons pointed toward a vision that could finally align with the original goals.</p><hr><h2 id="vision-the-why-%F0%9F%8F%9E%EF%B8%8F">Vision (the Why) &#x1F3DE;&#xFE0F;</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://images.unsplash.com/photo-1592997572272-d4a1e178b67a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG1hbGFnYXN5fGVufDB8fHx8MTc1NjgyMjgzNnww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" class="kg-image" alt="&quot;Serving a clear single purpose &quot; &#x2697;&#xFE0F;  Kahiether services" loading="lazy" width="5847" height="3898" srcset="https://images.unsplash.com/photo-1592997572272-d4a1e178b67a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG1hbGFnYXN5fGVufDB8fHx8MTc1NjgyMjgzNnww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=600 600w, https://images.unsplash.com/photo-1592997572272-d4a1e178b67a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG1hbGFnYXN5fGVufDB8fHx8MTc1NjgyMjgzNnww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1000 1000w, https://images.unsplash.com/photo-1592997572272-d4a1e178b67a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG1hbGFnYXN5fGVufDB8fHx8MTc1NjgyMjgzNnww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=1600 1600w, https://images.unsplash.com/photo-1592997572272-d4a1e178b67a?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG1hbGFnYXN5fGVufDB8fHx8MTc1NjgyMjgzNnww&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2400 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Photo by </span><a href="https://unsplash.com/@th3sand7?ref=kahiether.com"><span style="white-space: pre-wrap;">Sandy Ravaloniaina</span></a><span style="white-space: pre-wrap;"> / </span><a href="https://unsplash.com/?utm_source=ghost&amp;utm_medium=referral&amp;utm_campaign=api-credit"><span style="white-space: pre-wrap;">Unsplash</span></a></figcaption></figure><p>The vision of Kahiether is shaped by being constrained unnecessary weight and focusing on solving real problems.</p><blockquote> The single purpose is to build tools that directly address practical needs / problems. </blockquote><p>These are  concrete, everyday challenges: resizing images for administrative tasks, converting files to PDF, memorizing hanzi and kanji while learning languages, synchronizing files across devices, automating repetitive operations like retrieving website HTML. Each of these use cases is modest but real, and together they represent the kind of productivity gains that matter most.</p><blockquote>Another principle is acceptance of limitations.Kahiether does not aim to be the most secure system in the world. </blockquote><p>Instead, it reduces risk by design: no sensitive personal data is stored, most data lives offline, and the system is built to fail gracefully. If servers are attacked or fail, services are designed to restart quickly and continue functioning in offline mode. Basic protections like rate limiting are in place, but the goal is resilience, not absolute invulnerability.</p><blockquote>Portability is also central :Kahiether uses <a rel="noopener">Docker</a> and experiments with <a rel="noopener">Podman</a>, but avoids the complexity of <a rel="noopener">Kubernetes</a>.</blockquote><p> The aim is not to manage massive clusters but to keep services lightweight and flexible. Code is stored redundantly across different regions and providers: <a href="https://github.com/?utm_source=chatgpt.com" rel="noopener">GitHub</a> in the United States, <a href="https://gitlab.com/?utm_source=chatgpt.com" rel="noopener">GitLab</a> in Europe, and a third depot in China. This ensures continuity and independence.The microservice architecture is designed to be web-based but storage-independent. </p><blockquote>Progressive Web Apps (PWAs) allow mobile use while still functioning offline. </blockquote><p>Distribution is embraced as a way to reduce energy consumption: once a service is downloaded, it can run indefinitely without constant server calls, lowering CO&#x2082; impact. </p><blockquote>Technical debt is kept minimal : Kahiether&#x2019;s backend relies on only two dependencies: <a rel="noopener">Express</a> and <a rel="noopener">Node.js</a>.</blockquote><p> On the front end, there are zero dependencies. No bundlers like Webpack or Vite are used. This keeps the system light, transparent, and easy to understand.</p><p>This vision shaped the direction of Kahiether. The goal became clear: to create an ecosystem that could remain small in structure yet broad in utility.</p><hr><h2 id="birth-of-kahiether">Birth of Kahiether </h2><p>The name &#x201C;Kahiether&#x201D; brings together two symbolic ideas. </p><ul><li>&#x201C;Kahie&#x201D; &#x1F4D6; means book in Malagasy, a reference to structure, clarity, and the ability to preserve knowledge.</li><li> &#x201C;Ether&#x201D; &#x2697;&#xFE0F; referreds intially to a volatile element that filled space or void. Today it is still considered  as a volatile element used for example in dissolvents. </li></ul><p>Combined, the name represents a system that is both structured but very light, so light that it volatile,  very fluid, and flexible.</p><p>Kahiether ecocsytem was never meant to be a single microservice template. From the beginning, it was conceived as a system of multiple microservices and some opensource solutions forming an ecosystem. Each service would stand on its own but share the same design philosophy.</p><blockquote> Some  open-source components are integrated in the core ecosystem such as <a rel="noopener">Node-RED</a>, Docker, Ghost, Wordpress,  but the core remains independent and open-source.</blockquote><p>The creation of Kahiether was a gradual alignment of vision and practice.</p><hr><h2 id="features-%E2%9A%99%EF%B8%8F">Features &#x2699;&#xFE0F;</h2><p>Kahiether services are guided by a set of clear features that distinguish them from conventional approaches.</p><ul><li> O<strong>ffline-first functionality</strong>. &#x1F6DC;</li></ul><blockquote> Every service comes with a service worker, ensuring that files are stored locally. Once installed, a Kahiether service continues to work without internet access. </blockquote><p>Updates are fetched when connectivity is available, but core functions are always accessible. This makes Kahiether resilient in contexts where online connectivity cannot be guaranteed.</p><ul><li>L<strong>ight structure</strong>. &#x25AB;&#xFE0F;</li></ul><blockquote>A Kahiether service is built with three main files: <code>main.js</code>, <code>styles.js</code>, and <code>index.html</code>.</blockquote><p> An earlier file called <code>db.js</code> was used in older services but later removed to reduce complexity. No folders are used. Everything is visible at a glance. Each file is kept under 1,000 lines, including spacing, with verbosity preferred over compact optimization. The goal is transparency and readability rather than maximum efficiency.</p><ul><li><strong>Light Load.  </strong>&#x2696;&#xFE0F;</li></ul><blockquote>Less than 1vCPu and less than 500Mb of RAM for microservices.</blockquote><ul><li>R<strong>esponsivity</strong>. &#x1F4F1; </li></ul><blockquote>Each service includes a <code>manifest.json</code>, enabling installation as a PWA. I need to say goodbye to sinfle software with one codebase per platform :  one codebase in kotlin, one in Swift, one in C# ...</blockquote><p>This allows the same codebase to serve both web and mobile / tablets use cases without relying on separate applications.</p><ul><li><strong>Universality</strong>. &#x1F30D;</li></ul><blockquote> Services are written in plain JavaScript, without TypeScript or other abstractions. </blockquote><p>This choice accepts JavaScript&#x2019;s drawbacks&#x2014;such as loose typing&#x2014;but prioritizes universal compatibility. To reinforce universality, Unicode is embraced, including emoji, and only widely available fonts like Arial and Noto are used.</p><ul><li>Finally, Kahiether must be <strong>adaptable</strong>. Several services have already been created to showcase this philosophy in several domains such as:<ul><li><a href="https://mypa.kahiether.com/?ref=kahiether.com" rel="noreferrer">MyPa</a> :  indexing and multi task.</li><li><a href="https://shiro.kahiether.com/?ref=kahiether.com" rel="noreferrer">Shiro</a> : games</li><li><a href="https://nali.kahiether.com/?ref=kahiether.com" rel="noreferrer">Nali</a> : travel utilities with geolocation.</li><li><a href="https://resizer.kahiether.com/?ref=kahiether.com" rel="noreferrer">Resizer</a> : image resizing, text reading, and speech.</li><li><a href="https://yapishu.mino.randriamanivo.com/?ref=kahiether.com" rel="noreferrer">Yapishu</a> : e-learning through quizzes, writing, and listening.</li><li><a href="https://mpaka.kahiether.com/?ref=kahiether.com" rel="noreferrer">Mpaka</a> :  content extraction.</li><li><a href="https://kizuna.kahiether.com/?ref=kahiether.com" rel="noreferrer">Kizuna</a> : modular scripting and feature import.</li></ul></li></ul><p>Each of these services are not perfect, they serve a unique need insure that their main purpose is served.</p><hr><h2 id="perspectives">Perspectives</h2><p>The development of Kahiether is not a finished story. Several directions shape its future.</p><blockquote>One  perspective is the integration of lightweight artificial intelligence. </blockquote><p> &#x1F916; As models become smaller and more efficient, few candidates from <a href="https://huggingface.co/?utm_source=chatgpt.com" rel="noopener">Hugging Face</a> are being tested. Kahiether could incorporate these models, bringing powerful AI capabilities into offline-first services.</p><blockquote>Another direction is the creation of full list microservices that replicate what are currently large monolithic systems.</blockquote><p> &#x1F3EA; Entire domains such as e-commerce, customer relationship management, and enterprise resource planning are today dominated by heavy solutions. Kahiether has the potential to show that these same functions can be delivered by small, independent, resilient microservices without the overhead of massive platforms.</p><blockquote>Finally, the future of <a rel="noopener">Progressive Web Apps</a> could open even more opportunities.</blockquote><p> &#x1F4F4; As specifications expand and browsers provide deeper native integrations, PWAs may gain more capabilities to interact with devices and the Internet of Things. This would allow Kahiether services to extend naturally into new contexts, from mobile devices to connected environments.</p><hr><h2 id="it-is-what-it-is-%F0%9F%8F%9D%EF%B8%8F">It is what it is &#x1F3DD;&#xFE0F;</h2><p>To sum it up : Kahiether is not the fastest, nor the most secure, nor the most feature-rich system. It does not claim perfection. It offers services that are simple, transparent, lightweight, and resilient. It is a system that prioritizes usefulness over complexity, autonomy over dependence, and clarity over optimization.</p><p>Born from difficulties, refined through failures, and shaped by a clear vision, Kahiether is expression the vision that innovation often emerges from constraints. By keeping code minimal, dependencies light, and functionality offline-first, it shows that software can be practical without being heavy, and universal without being overloaded. My big hope for PWA is that one day they could run Daemon or cron like execution like native systems. Kahiether  future lies in extending these principles further, exploring new services with artificial intelligence, modular replacements for monolithic systems, and deeper capabilities through progressive web apps. Why ? because</p><blockquote>&#x2728;<strong>Some innovations emerge from the toughest conditions. Progress begins when open tools empower everyone, everywhere.</strong>&#x2728;</blockquote>]]></content:encoded></item><item><title><![CDATA[🏖️ Get once, always work, update if possible : Kahiether network strategies 🌐]]></title><description><![CDATA[<p>Hello,</p><p>Pre requirement : This strategy is very related to the microservice pattern where all the logic is stored fully in client side. We need to remember that this pattern doesn&apos;t works for use cases where some logic and data are manage by the distant server.</p><p>This time, we&</p>]]></description><link>https://kahiether.com/get-once-always-work-update-network/</link><guid isPermaLink="false">684e14c819fa5d0001fda07d</guid><category><![CDATA[News]]></category><dc:creator><![CDATA[敏 Ранд 🧭]]></dc:creator><pubDate>Sun, 15 Jun 2025 00:33:12 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1607027340690-37e80b0f1b31?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG9mZmxpbmV8ZW58MHx8fHwxNzU0NDUwMTA5fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1607027340690-37e80b0f1b31?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG9mZmxpbmV8ZW58MHx8fHwxNzU0NDUwMTA5fDA&amp;ixlib=rb-4.1.0&amp;q=80&amp;w=2000" alt="&#x1F3D6;&#xFE0F; Get once, always work, update if possible : Kahiether network strategies &#x1F310;"><p>Hello,</p><p>Pre requirement : This strategy is very related to the microservice pattern where all the logic is stored fully in client side. We need to remember that this pattern doesn&apos;t works for use cases where some logic and data are manage by the distant server.</p><p>This time, we&apos;ll explore how to build web applications and mobile / desktop PWA taking account of network constraints - from fiber-optic highways to the most challenging network environments on Earth. This story started 20 years ago in Madagascar.</p><h2 id="network-reality-check">Network Reality Check</h2><h3 id="when-56k-was-a-dream">When 56k Was a Dream</h3><p>Picture this: Madagascar,   2005 - 2010. While the  world was transitioning from dial-up to broadband, we were celebrating when our connection stayed stable long enough to download a single MP3 file. I personally remember spending 2-3 days downloading just a few megabytes, forcing to switch from direct download to using eMule and BitTorrent&apos;s partial download features to grab chunks.</p><p>The strategy was simple but effective:</p><ul><li>Download small chunks when possible</li><li>Resume from where we left off</li><li>Pray that some parts of the file is not missing</li><li>The file will be usable only if the full chunks are downloaded</li></ul><p>Sound primitive? Maybe. But it taught me invaluable lessons about resilience and the importance of designing for the worst-case scenario.</p><h3 id="fast-forward-to-today-not-much-has-changed">Fast Forward to Today: Not Much Has Changed</h3><p>We would think that 20 years later, with 4G, 5G, satellite network and fiber optics spreading globally, these problems would be ancient history. But, some of the challenges are still there:</p><ul><li><strong>Connection speeds</strong> might be better on paper, but reliability remains abysmal especially when moving out in the deep countryside</li><li><strong>Power outages</strong> are still frequent and long</li><li><strong>Network interruptions</strong> happen without warning</li><li><strong>Data costs</strong> make every megabyte precious</li></ul><p>The infrastructure has improved, but the fundamental challenges persist. This reality shaped my approach to building solutions that actually work for everyone, not just those with gigabit connections.</p><h2 id="the-problem-traditional-caching-strategies-fail">The Problem: Traditional Caching Strategies Fail</h2><h3 id="why-standard-approaches-dont-work">Why Standard Approaches Don&apos;t Work</h3><p>Most web caching strategies assume:</p><ol><li>Stable connections (even if slow)</li><li>Ability to complete HTTP requests</li><li>Predictable timeout behaviors</li><li>Power reliability</li><li>Stable servers (no attacks, no errors)</li></ol><p>In Madagascar-like conditions, these assumptions crumble:</p><p>When your connection drops every few minutes and power cuts mid-download, traditional cache-first or network-first strategies leave users stranded.</p><h2 id="the-solution-adaptive-resilience-strategy">The Solution: Adaptive Resilience Strategy</h2><h3 id="learning-from-p2p-the-chunking-philosophy">Learning from P2P: The Chunking Philosophy</h3><p>Remember how eMule and BitTorrent solved the download problem? They broke files into chunks, grabbed what they could, and assembled the pieces later. We can apply similar thinking by considering each file as chunk to web apps, and add a microservice pattern to reduce the number of chunks managed in a single app :</p><p>javascript</p><pre><code class="language-javascript">const CONFIG = {
  CACHE_NAME: self.SW_CACHE_NAME || &apos;faritany-v2&apos;,
  TEMP_CACHE_NAME: self.SW_TEMP_CACHE_NAME || &apos;faritany-temp-v2&apos;,
  FIRST_TIME_TIMEOUT: parseInt(self.SW_FIRST_TIME_TIMEOUT) || 30000, // 30 seconds
  RETURNING_USER_TIMEOUT: parseInt(self.SW_RETURNING_USER_TIMEOUT) || 5000, // 5 seconds
};</code></pre><h3 id="the-strategy">The Strategy </h3><p>After a few years of refinement, here&apos;s the  last approach that has proven successful since now :</p><h4 id="1-first-contact-maximum-patience">1. <strong>First Contact: Maximum Patience</strong></h4><p>New users need to download the app at least once. We give them every chance and time to fetch all the assets:</p><pre><code class="language-javascript">async function fetchFromNetworkWithExtendedTimeout(request) {
  try {
    console.log(`Service Worker: First time user - extended network timeout: ${request.url}`);
    
    // Extended timeout for first-time users (30 seconds)
    const timeoutPromise = new Promise((_, reject) =&gt; {
      setTimeout(() =&gt; reject(new Error(&apos;Network request timeout - first time user&apos;)), CONFIG.FIRST_TIME_TIMEOUT);
    });
    
    const networkResponse = await Promise.race([
      fetch(request),
      timeoutPromise
    ]);
    
    if (!networkResponse.ok) {
      throw new Error(`Server error: ${networkResponse.status}`);
    }
    
    // SUCCESS: Cache for future use
    console.log(`Service Worker: First time success - caching: ${request.url}`);
    const cache = await caches.open(LIVE_CACHE);
    cache.put(request, networkResponse.clone());
    
    return networkResponse;</code></pre><p>This mirrors the patience we had downloading files 20 years ago - sometimes you just need to wait for that one good moment.</p><h4 id="2-returning-users-try-network-of-fallbacks">2. <strong>Returning Users: Try network of fallbacks</strong></h4><p>When a user returns, he already have a working version on his cache, so if he has network we  try to update, but if  the update takes too much time to complete, then we cut the update and fallback on cache:</p><p>javascript</p><pre><code class="language-javascript">    // Create timeout promise (5 seconds max wait)
    const timeoutPromise = new Promise((_, reject) =&gt; {
      setTimeout(() =&gt; reject(new Error(&apos;Network request timeout&apos;)), CONFIG.RETURNING_USER_TIMEOUT);
    });
    </code></pre><h4 id="3-power-outage-protection-atomic-updates">3. <strong>Power Outage Protection: Atomic Updates</strong></h4><p>Nothing&apos;s worse than a half-updated app after power returns. So we need to check that everything is updated before switching the existing version:</p><p>javascript</p><pre><code class="language-javascript">// Install: Download all assets into a temporary cache.
self.addEventListener(&apos;install&apos;, event =&gt; {
  console.log(&apos;Service Worker: Installing...&apos;);
  self.skipWaiting(); // Force immediate activation
  
  event.waitUntil(
    caches.open(TEMP_CACHE).then(tempCache =&gt; {
      return Promise.all(
        ASSETS.map(url =&gt; {
          return fetch(url).then(response =&gt; {
            if (!response.ok) {
              throw new Error(`Failed to fetch ${url}: ${response.status}`);
            }
            console.log(`Service Worker: Cached ${url}`);
            return tempCache.put(url, response.clone());
          }).catch(error =&gt; {
            console.error(`Service Worker: Failed to cache ${url}:`, error);
            // Continue with other assets even if one fails
            return null;
          });
        })
      );
    })
  );
});

// Activate: Replace live cache ONLY if ALL assets are staged
self.addEventListener(&apos;activate&apos;, event =&gt; {
  console.log(&apos;Service Worker: Activating...&apos;);
  event.waitUntil(
    (async () =&gt; {
      const tempCache = await caches.open(TEMP_CACHE);
      const cachedRequests = await tempCache.keys();
      
      // ALL ASSETS ARE CRITICAL - Strict verification
      if (cachedRequests.length === ASSETS.length) {
        console.log(&apos;Service Worker: ALL assets staged successfully, updating live cache&apos;);
        
        // Complete atomic replacement
        await caches.delete(LIVE_CACHE);
        const liveCache = await caches.open(LIVE_CACHE);
        
        // Copy ALL assets from temp cache to live cache
        for (const request of cachedRequests) {
          const response = await tempCache.match(request);
          await liveCache.put(request, response);
        }
     </code></pre><h3 id="real-world-implementation-details">Real-World Implementation Details</h3><h3 id="cache-lock-rescue">Cache lock rescue</h3><p>At the time of this update some code was already running with a specific version, so we need to implement the rescue process. The main issue that must be checked is the cache lock, so the solution is to intercept the main.js and inject inside of it the rescue code.</p><pre><code class="language-javascript">// server.js
const express = require(&apos;express&apos;);
const path = require(&apos;path&apos;);
const fs = require(&apos;fs&apos;);
const app = express();


// CACHE VERSION MANAGEMENT - Change this to deploy new version
const CACHE_VERSION = process.env.CACHE_VERSION || &apos;v2&apos;;
const APP_NAME = process.env.APP_NAME || &apos;faritany&apos;;

// Cache Lock Rescue - Intercept main.js to inject rescue code
app.get(&apos;/main.js&apos;, (req, res) =&gt; {
  try {
    // Read the actual main.js file (your existing game/app code)
    let jsContent = fs.readFileSync(path.join(__dirname, &apos;main.js&apos;), &apos;utf8&apos;);
    
    // Inject ONLY the rescue detection code at the beginning
    const rescueCode = `
// Cache Lock Rescue - Check for ${CACHE_VERSION} users and free older versions
if (&apos;serviceWorker&apos; in navigator) {
  caches.keys().then(cacheNames =&gt; {
    const hasCurrentVersion = cacheNames.some(name =&gt; name.includes(&apos;-${CACHE_VERSION}&apos;));
    
    if (!hasCurrentVersion &amp;&amp; cacheNames.length &gt; 0) {
      // Old version detected - unregister and reload
      console.log(&apos;Cache lock detected - rescuing to ${CACHE_VERSION}...&apos;);
      navigator.serviceWorker.getRegistration().then(reg =&gt; {
        if (reg) reg.unregister().then(() =&gt; location.reload());
      });
      return; // Stop here for old version users
    }
    
    // Current version users or new users - normal service worker registration
    navigator.serviceWorker.register(&apos;/service-worker.js&apos;, {updateViaCache: &apos;none&apos;});
  });
}
`;</code></pre><h2 id="lessons-from-the-field">Lessons from the Field</h2><h3 id="what-really-matters">What Really Matters</h3><ol><li><strong>Assume Nothing</strong>: That 4G/5G signal might drop to EDGE without warning or come back to normal without warning</li><li><strong>Cache Everything</strong>: Every byte downloaded is precious</li><li><strong>Fail Gracefully</strong>: Errors should guide, not frustrate</li><li><strong>Background Updates</strong>: Never completely block the user experience </li><li><strong>The user usually manages to cut itself his data when it is not unlimited</strong>: Most user switch off data and uses specific prices for Facebook mobile only and Whatapp mobile only</li></ol><h3 id="the-bigger-picture">The Bigger Picture</h3><h3 id="why-this-matters">Why This Matters</h3><p>Building for challenging situations is inside Kahiether&apos;s DNA. </p><ol><li><strong>Performance Benefits Everyone</strong>: Optimizations for slow networks make fast networks blazing, because it&apos;s a network first strategy, those with very good internet speed will not notice anything different.</li><li><strong>Resilience is Universal</strong>: Power outages might happen in Silicon Valley too.</li><li><strong>Future-Proofing</strong>: Today&apos;s edge case is tomorrow&apos;s standard requirement. We don&apos;t know maybe tomorrow we will use these apps in the moon, in the space, in Mars, under the Ocean &apos;s Abysses </li><li><strong>Global Market Access</strong>: Billions of users are in emerging markets </li></ol><h3 id="beyond-madagascar">Beyond Madagascar</h3><p>There is so much devices in the world, I have particularly noticed users that have more than one smartphone when double SIM wasn&apos;t that popular. Some of them uses a phone with an Orange SIM because they give unlimited Facebook for a day for a certain amount, and another phone with a Telma (Yas) SIM because the network is cheaper for every Mb consumed. But these patterns apply everywhere in a lot of different situations:</p><ul><li><strong>Rural Areas</strong>: Spotty coverage in developed countries</li><li><strong>Transportation</strong>: Subways, flights, tunnels</li><li><strong>Emergencies</strong>: When infrastructure fails</li><li><strong>Cost-Conscious Users</strong>: Those managing data budgets</li></ul><h2 id="wrapping-up">Wrapping Up</h2><p>Twenty years after struggling to download files in Madagascar, the core challenges remain remarkably similar. But now we have better tools and strategies to handle them. The key insights:</p><p>Building truly resilient web applications requires embracing the reality that good networks are the exception, not the rule. Whether it&apos;s a specific country challenging infrastructure or a subway tunnel in New York, our apps should work everywhere, for everyone.</p><p>This strategy consists on three main steps : </p><p>Get once : get the app once</p><p>Always works : cache everything for work offline</p><p>Update if possible : update only if you are sure to be able to make a full update</p><p>This is not the perfect solution, but it is what it is. Switching frow the two network environment really taught me one lesson : </p><blockquote><strong>Some innovations emerge from the toughest conditions. Progress begins when open tools empower everyone, everywhere.</strong></blockquote><p>See you next time! &#x1F30D;</p>]]></content:encoded></item></channel></rss>