Reaching browsers reliably with Temporal and durable sessions
TL;DR Temporal makes backend Workflows crash-proof through durable execution: if a process dies mid-task, it picks up from the last checkpoint instead of starting over. Temporal shipped Workflow Streams in Public Preview at Replay 2026, for Python first and TypeScript from 17 June. It doesn't replay missed Events when users reconnect, support multiple devices, or notify offline users. To make agent-to-user interactions crash-proof, you need a durable session layer running in parallel with Temporal. Ably AI Transport provides one, with a documented Temporal integration available today.
Temporal solves a hard problem well. When an AI agent crashes mid-task, durable execution picks up from the last checkpoint without repeating work. The backend state is always consistent and recoverable.
The question that follows every Temporal adoption is the same: how do results get to the user's screen? Temporal doesn't answer that question, and its own team says so plainly.
What Temporal handles
Temporal makes backend logic crash-proof through event sourcing and checkpointing. It records every completed Activity. If the process dies, a new instance reads the Event History and continues.
Long-running Workflows (days, weeks, months) survive infrastructure failures without losing position. Human-in-the-loop patterns work because a paused Workflow can receive a Signal hours or days after the pause.
Temporal's Event History is the authoritative record of what the agent is doing and what it has done.
What Temporal doesn't handle
Before Workflow Streams shipped at Replay in May 2026, there was no built-in way to push Workflow state to a frontend. Teams needed a separate service in the middle to receive and relay messages to the UI.
Workflow Streams, now available in public preview for Python and TypeScript, uses Signal and Update primitives to stream token batches from Workflows to connected clients. But it still doesn't address multi-device fan-out, push notifications for offline users, or session durability when clients disconnect, in either language.
That leaves four consistent gaps between what Temporal is built to do and what an AI agent's frontend needs:
Replay for reconnecting browser clients. When a user's browser disconnects mid-workflow and reconnects, there is no replay. The Workflow state is fine. But the user sees nothing of what happened while they were gone.
Fan-out to multiple simultaneous observers. Temporal's message passing primitives are point-to-point between a client and a specific Workflow Execution. Multiple browser tabs, devices, or users watching the same Workflow must each independently poll or query. There is no broadcast primitive. See Delivering Temporal workflow output to multiple devices for why that doesn't scale by device count.
Notifications for offline users when Workflows complete. When an agent finishes a long task and the user has navigated away, there is no built-in notification mechanism. The result sits in Workflow state until someone queries it.
Low-latency streaming for LLM tokens. Temporal's minimum Workflow step latency is around 100ms, and a single Activity adds approximately 120ms of overhead. High-frequency token streaming hits both this latency ceiling and the 50MB Event History limit. Temporal's own documentation acknowledges "there are valid objections for Temporal to be in the hot path for interactive user transactions."
Your options for delivering Temporal's output to a user's screen
Teams keep arriving at the same five approaches.
Polling the query handler
Most teams start here. Your Workflow exposes state via a Query handler and the frontend calls it on a timer. For low-traffic applications with infrequent updates, it works.
At scale, the cost mounts. At 1,000 active users polling every two seconds, that's 500 requests per second before any Workflow work starts. Temporal Cloud prices by actions, and the visibility API has rate limits that degrade under this load.
Redis pub/sub
A common next step: the Workflow publishes tokens to Redis, and a relay layer forwards them to SSE endpoints. This decouples generation from delivery and handles simple single-device cases where the user stays connected.
Fire-and-forget delivery means Events published during a disconnect are gone. The developer at Architecting Bytes who built this architecture in production was direct: "This is NOT a durable delivery format, it is purely fire-n-forget." There is no catch-up for reconnecting clients.
Setting this up means running a relay service that bridges Redis and SSE/WebSocket connections. You'll also need your own reconnect and catch-up logic if you want to close the gaps above. See Redis pub/sub limitations for Temporal frontend delivery for the full failure-mode breakdown and where Redis pub/sub is genuinely enough.
Sticky sessions
Routing every request from the same user to the same server preserves whatever is in memory. When that server restarts or you scale out, the in-memory state goes with it. The user reconnects on a different machine that has no record of what the agent was doing.
Sticky sessions are server affinity, not session persistence. This requires load-balancer configuration for session affinity, and doesn't reduce complexity anywhere else in the stack.
Custom WebSocket server
For a bidirectional channel and persistent connections, teams move to dedicated WebSocket infrastructure outside Temporal. You get a proper two-way channel, but connection management, reconnection logic, backpressure, and lifecycle handling all become yours to own.
Custom WebSocket infrastructure is a gap Temporal has acknowledged rather than solved: building it yourself typically means recreating most of a realtime platform from scratch.
Purpose-built delivery layer
A delivery layer designed for agent Workflows handles durable sessions alongside Temporal's durable execution. This is increasingly referred to as a durable session layer.
When a Workflow Activity completes, it publishes the result to a session. Any client subscribed to that session receives it. A user who disconnects and reconnects gets caught up from their last position.
A second device joins the same session and receives the same stream. When the agent crashes and Temporal restarts it, the new instance checks what was already published and resumes. The user sees continuation, not duplication.
Some teams try to skip the session layer entirely and store conversation state inside the Temporal Workflow instead. But chat-heavy Workflows can reach the 51,200-Event History limit faster than expected, especially with polling-based state checks.
An immutable execution log can't represent message edits, deletions, or partial stream rewrites. Fan-out to multiple devices still requires a separate layer regardless of where the transcript lives.
See Managing conversation history in a Temporal AI agent chat for what breaks when teams take that shortcut. Ably AI Transport is one implementation of this pattern.
Choosing between these approaches
First, decide what you actually need: reconnect replay, multi-device fan-out, offline notifications, or low-latency control signals like cancel. That tells you which approach fits your use case.
If you don't, and your scope is a single connected device, then polling and Redis pub/sub might be sufficient.
But if these are key to your product, you have a choice. Use sticky sessions or a custom WebSocket server with logic that you build and maintain yourself. Or use a durable session layer, which provides it out of the box.
And remember: Temporal and a durable session layer aren't alternatives. They solve different problems, and most production AI agents need both. This table summarizes when the session-layer piece becomes necessary.
| Scenario | Durable sessions? | Why? |
|---|---|---|
| Server-to-server batch, no user-facing component | No | Temporal handles this entirely |
| Simple single-user Workflow, user stays on the page | Minimal | Polling or Workflow Streams covers the basics |
| Long-running agent, user may navigate away | Yes | Notifies user on return, on any device |
| Human-in-the-loop approval flows | Yes | Pushes approval request to the right person across devices |
| Live progress visibility during multi-step agents | Yes | Real-time updates without polling workers |
| Agent cancel or steer mid-run | Yes | Delivers control signals in milliseconds, not on next Workflow turn |
| Multi-device or multi-tab continuity | Yes | Live stream that follows the user to a second device. See Delivering Temporal workflow output to multiple devices |
What to look for in a session layer
These four properties apply to any session layer sitting alongside a durable-execution backend, not just Temporal. Most implementations cover one or two of these properties. All four together are what separates a durable session from the workarounds that break in production.
- Persistent: survives disconnects. Buffers and replays messages in order after a disconnect, which is what AI Transport's reconnection and recovery feature provides.
- Addressable: reachable across devices and resets. An ephemeral connection ID that disappears when the connection closes doesn't cut it. The session needs a stable identity that persists independently of any single Workflow Execution, so a Temporal restart doesn't interrupt it. This is AI Transport's sessions concept.
- Presence-aware: knows who's connected. Without this, agents burn inference on responses nobody is receiving, and UIs show activity indicators for agents that have already stopped. Presence needs to be a first-class state transition, not something inferred from a timeout, which is what AI Transport's agent presence feature provides.
- Multi-participant coherent: works regardless of reconnect order. Stays consistent no matter which side, agent or user, reconnects first, which is what AI Transport's multi-device sessions feature delivers.
Temporal and AI Transport: solving durable sessions
A session layer needs to do all of this alongside Temporal. Ably AI Transport ships that as a documented integration, not just a compatible shape.
Each Temporal Activity's output is published as a Step. The Activity's own Temporal Activity ID becomes the step ID through a stepIdFor helper.
When Temporal retries a failed Activity, Ably publishes the retry under the same step ID. It supersedes the failed attempt on the session instead of appending a duplicate.
Cancels route through the Ably session directly. A stop button in the browser fires the Activity's abort Signal without a Temporal Signal in the loop.
Adopting this means wrapping Activity calls with the stepIdFor helper and subscribing the frontend to the resulting Ably session. It's a mapping exercise on an existing Temporal deployment, not a rebuild of your delivery layer.
Ably's documentation names this the reference integration for durable execution. See the Temporal integration guide for the full API. For the framework-agnostic pattern it's built on, see durable execution, which also covers Vercel WDK, Vercel's own workflow durability toolkit.
Ably AI Transport is a durable session layer for Temporal and other durable execution frameworks. It handles resumable streaming and multi-device delivery today, with push notification support for offline users currently rolling out across sessions. Visit the Ably AI Transport overview, read the documentation, or sign up free to start building.
Frequently asked questions
Does Temporal have a built-in way to push Workflow output to a browser?
Yes, partially, since Workflow Streams shipped in 2026 for Python and TypeScript Workflows. It's real, but narrow: reconnect replay, multi-device fan-out, and offline notifications still aren't covered.
If I've already adopted Workflow Streams, do I still need a session layer?
For a single device that stays connected, Workflow Streams alone is often enough, since reconnect works out of the box. The moment a second device, an offline notification, or a disconnected client's catch-up matters, you're back to needing a session layer. Those are the exact gaps Workflow Streams doesn't close, in either supported language.
Can I get by with just querying my Temporal Workflow instead of building a session layer?
Only for a narrow case: a single device that's currently connected and wants a one-time state check. A Query returns whatever the Workflow currently holds, not the ordered sequence of Events that produced it. That means a UI built on queries alone can't show streaming tokens correctly, can't tell you what changed since the last check, and gives you nothing to replay for a device that reconnects.
What are my options for delivering Temporal Workflow output to a frontend?
There are five: polling, Redis pub/sub, sticky sessions, a custom WebSocket server, or a purpose-built delivery layer. Which one you need depends on whether reconnect replay, multi-device fan-out, or offline notifications matter for your use case, not on setup effort alone.
When does a Temporal application need a separate session layer?
As soon as a user might navigate away, use more than one device, or need a control signal like cancel delivered faster than the Workflow's own turn-taking allows. Pure server-to-server batch work, with no user-facing component, is the one case that doesn't need it.
Does Ably have a Temporal integration?
There's real, purpose-built tooling for it, not a fully managed drop-in. The stepIdFor helper derives a Step ID from each Temporal Activity ID. A retried Activity then supersedes its own output on the session instead of duplicating it. You wire this into your own Activity calls: Temporal and Ably AI Transport remain two separate products working together, not one packaged SDK.
Recommended Articles
Redis pub/sub limitations for Temporal frontend delivery
Redis pub/sub is fire-and-forget. Events published while a client is disconnected are gone permanently. Why it falls short for Temporal workflows and what to use instead.
Delivering Temporal workflow output to multiple devices
Polling and Redis pub/sub both fail the same way with Temporal: the second device joins broken. Here's what actually solves it.
Managing conversation history in a Temporal AI agent chat
A Temporal AI agent's conversation transcript can split across two workflow executions. Here's why, and how to keep transcript storage separate instead.