NeloRequest ownership runtime

Every request owns its work.

Nelo is a Web Standards framework for TypeScript that makes child tasks, cancellation, resource cleanup, and response delivery explicit parts of the request lifecycle.

app.tsHandler Scope
app.ts
import { Nelo } from "nelo";

const app = new Nelo();

app.get("/users/:id", async (context) => {
  const user = context.fork("user", (signal) =>
    fetchUser(context.params.id!, { signal })
  );

  const feed = context.fork("feed", (signal) =>
    fetchFeed(context.params.id!, { signal })
  );

  return context.json({
    user: await user,
    feed: await feed,
  });
});
phase04 complete
tests62 passing
repository0 stars · 0 issues
licenseApache-2.0
01 / Model

Request ownership

Async work needs a boundary.

A handler returning does not always mean the request is finished. Nelo separates work owned by the handler from work required while the response body is still being delivered.

A
Handler Scope

middleware · route handler · context.fork() · context.use()

settles first
B
Delivery Scope

Response.body · delivery.fork() · delivery.use()

closes last
01

Child work has an owner.

context.fork() creates a named task that belongs to the current request. It cannot quietly become an untracked promise.

context.fork("profile", (signal) => loadProfile({ signal }))
02

Cancellation keeps its reason.

The same cooperative signal travels through child scopes while the first abort reason remains available for diagnostics.

context.signal.reason // client_disconnect
03

Cleanup runs once.

Resources are released in reverse acquisition order after the work that owns them has settled.

context.use("database", connect, (db) => db.close())
02 / Live API

Server-backed lifecycle demo

Run the boundary.

The demo calls a real Next.js route and returns the Handler and Delivery timeline for success, disconnect, and producer failure.

POST /api/lifecyclewaiting

Select a scenario and run the request.

The response is generated by the server route, not mocked in the browser.
03 / Surface

Small API

Normal TypeScript, explicit ownership.

Owned taskscontext.fork(name, operation)
Cancellationcontext.signal
Resourcescontext.use(name, acquire, cleanup)
Deliverycontext.delivery.fork() / use()
Request Response ReadableStream AbortSignal
04 / Runtimes

Runtime capabilities

Portable core. Honest adapters.

Support is shown only after real transport behavior and tests exist.

CapabilityCoreNode.jsCloudflareDenoBun
Request scopesCoreCoreCore
Owned tasksCoreCoreCore
Resource cleanupCoreCoreCore
Client disconnectPlannedPlannedPlanned
Delivery trackingPlannedPlannedPlanned
Graceful shutdownPlannedPlannedPlanned
05 / Roadmap

Built in phases

Claims backed by tests.

Phase 4 completes the Handler and Delivery lifetime split. The next work is runtime-specific.

01

Ownership core

Lifetime scopes, owned tasks, typed cancellation, and deterministic resource cleanup.

Complete
02

Portable web surface

Fetch-style application API, router, middleware, context helpers, and error boundaries.

Complete
03

Node transport

Real socket disconnect tests, delivery tracking, graceful shutdown, and CI.

Complete
04

Handler + Delivery

Separate lifetimes, delivery-owned work, typed abort reasons, and request diagnostics.

Complete

More runtimes

Cloudflare, Deno, and Bun adapters, deferred work, and diagnostics tooling.

Planned

Experimental software

Make request lifetime part of the program.