Back to the journal

Real-time systems / 2 MIN READ

Streaming is a lifecycle, not a text effect

The first token is the beginning of a conversation with the interface, not the end of the engineering.

Sai Sri Harsha Guddati ·

A streaming answer feels immediate because the user sees progress before the work is finished. Behind that effect sits a lifecycle: admission, execution, partial output, completion, interruption, and cleanup.

My real-time work includes Redis Pub/Sub, Celery, and server-sent events. The interesting part is not merely moving text across those components. It is keeping the browser's picture of the job consistent with what the system is doing.

Give states names

An illustrative workflow might move through accepted, queued, running, streaming, and completed. It also needs cancelled and failed. These states should not be inferred solely from whether a connection is open.

An open connection can carry no useful work. A closed connection can follow a completed answer or an interrupted one. The client needs an explicit terminal event, and the server needs a clear rule about when that event is recorded.

SSE provides a browser-facing event format, including named events and event IDs. Those primitives help carry a lifecycle, but the application must define its semantics. MDN's SSE guide is a useful reference for the transport.

Separate work from observation

The worker owns execution. The browser observes it. That distinction becomes important when a tab closes or a connection drops.

Does the job continue? Can the user reconnect? Does cancellation mean stopping delivery, stopping the worker, or both? The answer depends on the workflow, but it should be explicit. Otherwise, “stop generating” can become a button that only hides activity while resources continue to run.

A job ID creates a stable identity across these changes. The connection is temporary; the job may outlive it.

Close the loop

Completion should be durable enough for the interface to confirm what happened. Cleanup should release subscriptions and buffers. Failure should explain whether retrying starts a new job or resumes an existing one.

I like to review a streaming design by asking what happens if the browser disappears at every transition. That exercise makes hidden coupling visible quickly.

A polished stream is not one that never interrupts. It is one that can explain an interruption without losing the identity of the work. The typing effect is pleasant. The lifecycle is what makes it a system.

More from the journal