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 aliveOn 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
| Concern | Redis + API | Room DO |
|---|---|---|
| Ordering | Requires careful channel design | Single-threaded DO per room |
| History on join | Separate DB fetch | Same connect snapshot |
| Idle cost | Always-on subscribers | Hibernation: pay when active |
| Global latency | Central region | Cloudflare 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
serializeAttachmentfor 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)