FluxyChat

Realtime & Streaming

Edge room history and hibernation

How FluxyChat uses Durable Objects, WebSocket hibernation, and D1 for room history at the edge.

Each FluxyChat room runs as one Durable Object with WebSocket hibernation. Clients stay connected while the DO sleeps, which cuts duration charges compared with always-on Node or Redis stacks.

Architecture

Client --WebSocket--> Room DO (single-threaded)
                         |
                         +-- D1: message history (authoritative)
                         +-- DO storage: presence, streams, attachment refs
                         +-- Hibernation: ctx.acceptWebSocket() keeps sockets alive

On connect, the DO sends a history snapshot (type: history or replay) with:

  • Messages from D1 (visibility-filtered)
  • Attachments enriched
  • Polls with vote counts and userVote
  • Reaction tallies

Why edge beats Redis pub/sub for chat rooms

ConcernRedis + APIRoom DO
OrderingRequires careful channel designSingle-threaded DO per room
History on joinSeparate DB fetchSame connect snapshot
Idle costAlways-on subscribersHibernation: pay when active
Global latencyCentral regionCloudflare edge POP

PubNub and Ably excel at fan-out primitives. FluxyChat optimizes authoritative room state and chat UX on a DO.

Agent streaming keep-alive

From June 2026, an active outbound fetch or WebSocket from a DO prevents eviction for up to 15 minutes. LLM token streaming uses fetchWithDoKeepalive in llm-stream.js so agent runs are less likely to stop mid-stream.

Operational notes

  • Use serializeAttachment for user metadata across hibernation wakeups
  • Batch poll attach on history: attachPollsToMessages()
  • Apply D1 migrations before deploy; history queries are indexed by (project_id, room_id, created_at)

On this page