Updates

23 October 2026 — node v0.24.6, client 0.19.1.

This is an archived entry. See the latest update.

Previous update: 16 October 2026 — The hammering is gone

When a connection ends, its processor should too

A closed network connection should stop costing the node work. In Evolver, closing the socket did not always end the life of the event processor behind it. The connection was gone, but its empty processor could remain registered, leaving the dispatcher to keep checking something that would never do useful work again.

That is a quiet kind of overhead. A single leftover processor is unremarkable; repeated short-lived connections turn connection history into continuing scheduling work. Today's fixes address that lifecycle mismatch, and the races that make “just remove it” an unsafe answer.

End the lifetime where it is owned

Evolver v0.24.6 uses the published sss-events 0.0.16 release and its self.unRegister() operation. A connection processor declares its own terminal completion from inside its event handler. Pending work is discarded, subscriptions and registration are removed, and the processor is not returned to the dispatcher for another turn. The current handler can finish without waiting for its queued messages to drain.

Ownership matters here. Asking a shared worker to wait for the closing processor would put unrelated connections behind cleanup. Retiring from the processor's own handler gives terminal completion a clear place in the normal event flow instead.

The integration also respects the actual released API: each connection gets a fresh generated processor identifier, registration completes before close callbacks are exposed, and a retired instance is never registered again. This is not a general promise that identifiers can be reused safely or registration can race retirement.

Nor is it a redesign of scheduling for legitimate idle connections. The fix removes completed lifetimes. Terminal events still need to reach a running processor's bounded mailbox; it does not solve lost control messages under mailbox overload.

A peer name is not a connection lifetime

Two connections can briefly belong to the same peer while replacement and duplicate resolution are in progress. Cleanup keyed only by peer identity can therefore remove the wrong thing.

Close notifications and actionable connection errors identify the exact originating processor. If an old connection's write fails after its replacement has been selected, the error must close the old connection—not whichever connection now occupies that peer's slot. Oversized-payload rejection follows the same rule.

Pending promotion needs another check. A candidate can retire before its close notification reaches the network handler, leaving a pending-map entry that looks valid but no longer represents a live processor. Before promotion can close the active connection, Evolver checks that the candidate still owns its exact registration. A stale candidate is discarded without sacrificing the healthy connection. That is a point-in-time check, not a claim that a candidate can never fail afterwards.

Shutdown has an admission boundary too. A connection that finishes establishing after shutdown has begun is told to close rather than announced as a new peer or admitted for sending. Closing existing connections is not enough if late arrivals can recreate the work being shut down.

Preserve the failure, even when close wins

A second race involved Netty's write and close callbacks. An underlying write error can complete closeFuture before outstanding write promises report failure. The close event can retire the connection processor first, so a later write-failure message is correctly refused—but its diagnostic can disappear with it.

Both write helpers now log the actual write cause from the completion callback, independently of whether the processor can still accept a message. Actionable connection errors remain owned by the open handler and retain their exact origin. This preserves the diagnostic without reviving a retired processor or changing an already auto-closed connection's existing terminal reason.

The tests exercise Netty's real auto-close ordering and check that the written buffer's reference count reaches zero. That buffer-ownership assertion is deliberately narrower than a claim that the entire application is leak-free.

Make the ordering observable, not lucky

These are concurrency fixes, so sleeping for a while and hoping callbacks have finished would be weak evidence. The lifecycle tests use explicit completion signals and queue fences to arrange the relevant ordering, then check both cleanup and survival: the closed processor is gone, and the unrelated or replacement connection still handles work.

Verification against the externally resolved stable dependency passed 49 focused tests and 3,330 full unit tests. Four existing opt-in tests remained cancelled, not counted as executed. Statement coverage was 53.02%, above the 45% gate. A separate, official full isolated regression completed with 34 passing stages, no failures and no pending stages.

Those results are not a warning-free verdict: compilation reported 607 warnings. An unchanged content-test fixture also exposed an unconsumed buffer condition reproduced with both dependency versions. That bounded comparison does not explain away the separate, unresolved production Netty aggregator leak report.

A gate must run on every supported path

Today's CI-script repair addresses a different lifecycle problem: process control flow. The root execution path used exec when dropping privileges, so a later shipped-skill check could be skipped. The root path now re-enters the same script as an unprivileged user, so the existing shared tail—npm ci, npm test and the shipped-skill check—executes on both paths.

The eight-case control-flow harness went from six passing cases to eight, and actual local root privilege-drop and shared-tail checks passed. The repair has been merged and pushed. The private CI result remains unknown; these reproductions establish the script defect and local correction, not the cause of an unseen failed remote job.

Verify the release, then verify the rollout

Core v0.24.6 is published and independently content-verified, including the actual stable sss-events 0.0.16 dependency in the node distribution. A tag alone would not establish that: the delivered contents need to match the reviewed and tested inputs.

The wider rollout remains staged. Companion artifact contents and deployment gates are being checked separately; release tags and artifact availability are not evidence that every managed node has been upgraded. Runtime health remains conditional while the production leak report is unresolved. This is not a completed-estate announcement.

For operators, the useful distinction is between source correctness, published content and a running service's health. Check each separately, retain warnings that still need investigation, and do not turn an available artifact into assumed deployment success.

For developers, the lesson is the same at a smaller scale: give each lifetime a clear owner, make stale callbacks identify what they actually belong to, and test the ordering that could break the survivor. Removing this polling tax addresses a concrete defect. We have not run a before-and-after transaction-latency benchmark, so we are not presenting it as a measured latency improvement.