PRO

Fluid Stream Lifecycle

A long-lived server-sent events endpoint on Vercel Fluid compute, written around the two things Fluid changes: how long a function may stay open, and who else is sharing the instance while it does. On classic serverless one invocation owned one instance and was billed for every wall-clock second, which priced streaming out of existence and made polling the standard advice; Fluid serves concurrent invocations from one instance and weights billing towards active CPU, so a handler that spends nine of its ten minutes awaiting an upstream token is no longer being charged as if it were alone. The route file is mostly lifecycle because that is where the new failure modes are: request.signal is threaded into the upstream fetch so a closed tab cancels the model request instead of streaming tokens nobody will read, an aborted stream is not logged as an error since otherwise the dashboard shows a large error rate that is entirely users closing tabs, the partial transcript is persisted from finally through waitUntil with a note that waitUntil shares the function timeout and is for cleanup rather than work that must not be lost, and the reader lock is released so the abort actually tears the socket down. The stream file holds the plumbing with the sharp edges: controller.enqueue accepts everything and buffers in memory regardless of whether the client is reading, which on a shared instance means filling memory for a client in a tunnel, so writes await desiredSize and give up on a deadline; close is guarded because the runtime may already have closed the stream after a disconnect and the throw would mask the real error; and the heartbeat returns its own stop function because an interval that outlives its stream now keeps a real invocation alive.

Install
npx shadcn@latest add https://ui.aryank.space/r/fluid-stream-lifecycle.json

Installs from ui.aryank.space. To add it by hand, copy the files in Files below, or register the @compronents namespace via the docs.

Visualization
outcome
stream
ReadableStream<Uint8Array>
FINALIZERS
try { await producer(send) } finally { stopHeartbeat(); controller.close() }

A long-lived SSE endpoint opens on Fluid compute; when the stream ends, the finally block unregisters the listener and closes the stream in reverse open order.

Files

Dependencies