<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luke Green</title>
    <description>The latest articles on DEV Community by Luke Green (@luke_gree_fc8780a9e7).</description>
    <link>https://dev.to/luke_gree_fc8780a9e7</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4133571%2F36a26086-5c63-4ddd-a6d9-38e3673fc74d.jpg</url>
      <title>DEV Community: Luke Green</title>
      <link>https://dev.to/luke_gree_fc8780a9e7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luke_gree_fc8780a9e7"/>
    <language>en</language>
    <item>
      <title>Drifting in the Void</title>
      <dc:creator>Luke Green</dc:creator>
      <pubDate>Fri, 16 Oct 2026 06:43:13 +0000</pubDate>
      <link>https://dev.to/luke_gree_fc8780a9e7/drifting-in-the-void-35eh</link>
      <guid>https://dev.to/luke_gree_fc8780a9e7/drifting-in-the-void-35eh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7qa934xrqn4svjwdvrbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7qa934xrqn4svjwdvrbd.png" alt=" " width="800" height="1126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You are drifting through an endless void, and your eyes meet nothing but the void. No stars, no comets, nothing. But you know there may be something far away. Or maybe your eyes have already met the eternal darkness. And it is just you.&lt;/p&gt;

&lt;p&gt;You try to move your body. However, you have no control over where you are travelling. It is taking you somewhere, and you do not know where you are going. There is no point of reference to tell you whether you are moving at all. You feel as though you are moving, but there is nothing you can do.&lt;/p&gt;

&lt;p&gt;This feeling closely resembles life. You take a moment and look around. You know there are things around you: opportunities, people, and things you enjoy. However, you are a person drifting in the void, someone who can move but cannot travel. &lt;/p&gt;

&lt;p&gt;You want to be somewhere else, maybe with someone you care about. You want to start your own business, have stable finances, or achieve something else you wish for. But you cannot travel the space between you and those things. There is a universe between you and the things you wish for.&lt;/p&gt;

&lt;p&gt;How unfortunate is it that the internet is filled with happy things? Everyone seems perfect and has the perfect life. Fair enough; maybe that is true. And you look at yourself and wish you were there.&lt;/p&gt;

&lt;p&gt;A better question would be: What sets you apart from the people who seem to be doing well in life? What are you missing?&lt;/p&gt;

&lt;p&gt;Imagine that, for one day, you could take over the body of someone you aspire to be, maybe a CEO, a senior engineer at a top company, or someone else. Do you think being in that person's body would also change how you feel?&lt;/p&gt;

&lt;p&gt;I think most things exist in a kind of balance, which might involve charisma, knowledge, skills, power, or something else. If that balance is missing, things tend to unfold in the opposite way. You can be a senior engineer or an investor for a day. However, would you possess all the knowledge and everything else required to hold that position?&lt;/p&gt;

&lt;p&gt;There are eight billion people. People are born with different privileges. Someone born in a developed country may have opportunities that someone born in a developing or underdeveloped country does not.&lt;/p&gt;

&lt;p&gt;Being born into a wealthy household, having educated parents, a healthy family and community, quality education, good friends, and the influence of people who can guide you can all make a difference. There could be infinitely many versions of your life, shaped by the decisions you make: the friends you choose, the college or school you attend, and so on. And you would never know what kind of person you might have become if you had been born into a different society, country, or family.&lt;/p&gt;

&lt;p&gt;As a human being, what are you supposed to do? How beautiful would it be if you could snap your fingers and be anywhere you wished to be? Or if you could simply change something about yourself, maybe a habit, your energy, your motivation, or something else. But life is nowhere near that easy. And it is not fair. Some people seem to get everything throughout their lives, while others spend their entire lives trying and still get nothing.&lt;/p&gt;

&lt;p&gt;So, the question might be: What is the point of trying at all if, in the end, it means nothing? We can do all the beautiful things in life, and yet we all share the same destination: death.&lt;/p&gt;

&lt;p&gt;What we do with the time we have is irrelevant to the universe, isn't it? It surprises me how unfazed the human species can be in the face of existence itself. Even if you are the president of a country or a scientist, the universe does not care about you. What you do in life is just a distraction from the truth, which is death itself. And that is the only truth.&lt;/p&gt;

&lt;p&gt;If everything in life is irrelevant, then why not try to do the things we want? Either way, we are just passing time. Why not choose the things that make these distractions a little more comfortable or bearable?&lt;/p&gt;

</description>
      <category>career</category>
      <category>writing</category>
    </item>
    <item>
      <title>Your plugin system couldn't replace plugins. So here's the transaction that you're missing.</title>
      <dc:creator>Luke Green</dc:creator>
      <pubDate>Sun, 20 Sep 2026 02:32:36 +0000</pubDate>
      <link>https://dev.to/luke_gree_fc8780a9e7/your-plugin-system-couldnt-replace-plugins-so-heres-the-transaction-that-youre-missing-21lm</link>
      <guid>https://dev.to/luke_gree_fc8780a9e7/your-plugin-system-couldnt-replace-plugins-so-heres-the-transaction-that-youre-missing-21lm</guid>
      <description>&lt;p&gt;What if an upgrade fails halfway through activating? The question would be: what is still running?&lt;/p&gt;

&lt;p&gt;In most plugin systems, the answer is: none. And in registries, the common bug could be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// the old plugin is already gone before the new one exists&lt;/span&gt;
&lt;span class="nx"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;setup()&lt;/code&gt; throws, the old working value is destroyed, and the new one never arrives. Now, your host is missing a capability it had a millisecond ago. In a daemon, that's an outage, not an error.&lt;/p&gt;

&lt;p&gt;This is the failure mode that matters most for systems which can't restart: long-running CLI daemons, editors, dev tools, and the new wave of AI-agent extension hosts, where shipping an upgrade should be routine, not a maintenance window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Replacing a live plugin is a transaction
&lt;/h2&gt;

&lt;p&gt;Moult treats it like one. A plugin is a versioned capability provider with an owned resource scope, and replacing it runs a protocol, not an assignment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setup&lt;/strong&gt; runs in a private scope — the candidate builds itself while the old generation keeps serving.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify&lt;/strong&gt; checks its provides and conflicts — staged capabilities stay invisible to observers until commit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit&lt;/strong&gt; swaps the active generation in a single atomic step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dispose&lt;/strong&gt; tears down the old generation, resources released in reverse acquisition order (LIFO).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If anything fails before the commit, the candidate scope is disposed, and the failure stays invisible: the previous generation remains active and usable. Like a crab, the system only sheds its shell once the new one is ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8t0umftp3m6z7m66kvgk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8t0umftp3m6z7m66kvgk.png" alt="Figure 1 — Moult runtime architecture. The capability registry resolves against the active generation; the generation manager prepares candidates in an isolated scope that stays invisible until commit." width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ~30 lines, zero downtime on failed upgrade
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;capability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createRuntime&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@moult/runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;capability&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRuntime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;memory.storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;provides&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;capability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;k&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;v1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]);&lt;/span&gt;
    &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;memory.storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// A broken replacement is rejected — and v1 keeps serving:&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;memory.storage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;provides&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;capability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bug in the new version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// REPLACEMENT_FAILED&lt;/span&gt;

&lt;span class="c1"&gt;// Usable, not just active: a consumer installed after the failure&lt;/span&gt;
&lt;span class="c1"&gt;// still binds the old generation's value.&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;capability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;range&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^1.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;seen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;k&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seen&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'v1' — the failed v2 never existed to readers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the entire guarantee, runnable: the rejection is a structured &lt;code&gt;MoltError&lt;/code&gt;, and a consumer installed after the failure still reads v1's value usable, not just active.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo4nyfljan19f94981mt1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo4nyfljan19f94981mt1.png" alt="Figure 2 — The replacement transaction. A failed candidate is disposed without ever becoming visible; a validated candidate swaps in atomically, and only then is the old generation disposed." width="800" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a second half to "versioned capability provider" that the snippet hides: capabilities carry a semver version, consumers declare semver ranges, and each token declares whether it accepts exactly one provider or aggregates many (&lt;code&gt;multiple: true&lt;/code&gt;). Resolution runs during preparation; a candidate whose requirements don't resolve fails before setup, so a version mismatch can never become visible either.&lt;/p&gt;

&lt;h2&gt;
  
  
  The guarantee is the test suite
&lt;/h2&gt;

&lt;p&gt;It's what's enforced. Nine replacement transaction tests cover failed setup, failed validation, disposal ordering, and resource cleanup, on top of property-based and stress suites: 145 tests, each run under both Node and a DOM environment — 290 runs, all green. The 15 invariants are written down in &lt;code&gt;docs/guarantees.md&lt;/code&gt;, and the repo's comparison harness runs the same failed-upgrade scenario against a naive registry, cordis, and Moult, publishing the raw numbers in &lt;code&gt;demo/comparison/RESULTS.md&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Runner&lt;/th&gt;
&lt;th&gt;Survives&lt;/th&gt;
&lt;th&gt;Leaked&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;naive registry&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cordis 4.0.0-rc.9&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@moult/runtime 0.1.1&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Excerpt — the full table adds the blocked-stop diagnostic and the average-ms column.&lt;br&gt;
&lt;em&gt;(Their caveat, which I'll repeat: environment-specific evidence, not a performance promise.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That safety isn't free: the whole benchmark scenario — install, one failed replace, and one hundred successful replaces — averages ~16ms against ~0.14ms for the naive registry (roughly ~0.16ms per replace in that environment, not ~16ms; scenario average, not per-call). You pay it per replace, never per capability read.&lt;/p&gt;

&lt;p&gt;A note on the neighbours: HMR reloads modules, and Module Federation shares them. Both are code-delivery mechanisms — neither promises that an upgrade either fully applies or fully rolls back. Moult owns a different layer: the replacement transaction itself. And if you use Vite, &lt;code&gt;@moult/vite&lt;/code&gt; routes module updates through the same replace path, so import/setup failures preserve the old generation and the bridge doesn't commit anything itself; the runtime's transaction does.&lt;/p&gt;

&lt;p&gt;The honest limits, because a runtime that hides its limits can't be trusted with your uptime: Moult is not a sandbox — plugins are trusted code, and it governs lifecycle and capability visibility, not permissions. It's not a loader or bundler; there's no global registry. And v1 refuses to silently rebind dependents — replacing a provider with active dependents is rejected outright with a structured &lt;code&gt;REPLACEMENT_FAILED&lt;/code&gt; error that names the dependent path, instead of quietly re-wiring them. Moult preserves service, not state: every generation gets a fresh scope, so in-memory handles don't migrate — React component state is explicitly not promised to survive replacement, and durable state belongs in a host-provided capability. The success path is just as strict: &lt;code&gt;replaced&lt;/code&gt; fires before the old scope is disposed, old resources release in LIFO order, and if the old generation's disposal fails after commit, the failure is recorded and inspectable — the replacement stands; there is no rollback.&lt;/p&gt;

&lt;p&gt;Around the runtime there's a small family: &lt;code&gt;@moult/events&lt;/code&gt; (generation-scoped typed events), &lt;code&gt;@moult/react&lt;/code&gt; (bindings for committed contributions), &lt;code&gt;@moult/test&lt;/code&gt; (utilities for proving ownership, replacement, and leak behaviour), and &lt;code&gt;@moult/vite&lt;/code&gt; (Vite HMR bindings that route module updates through the same transactional lifecycle).&lt;/p&gt;

&lt;h2&gt;
  
  
  Try breaking it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @moult/runtime  &lt;span class="c"&gt;# Node 22 or newer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/neryva-lab/moult" rel="noopener noreferrer"&gt;github.com/neryva-lab/moult&lt;/a&gt; — if you have an upgrade scenario your system can't survive, open an issue with the repro. I'd genuinely like to see it fail.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/neryva-lab/moult/blob/main/docs/guarantees.md" rel="noopener noreferrer"&gt;docs/guarantees.md&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/neryva-lab/moult/blob/main/demo/comparison/RESULTS.md" rel="noopener noreferrer"&gt;demo/comparison/RESULTS.md&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/@moult/runtime" rel="noopener noreferrer"&gt;@moult/runtime&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>architecture</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
