Use this file to discover all available pages before exploring further.
Durable Streams provides two modes for real-time streaming: long-polling and Server-Sent Events (SSE). Both modes support resumability and work seamlessly with CDN caching.
Long-polling waits for new data on each request, then returns and reconnects:
import { DurableStream } from "@durable-streams/client"const stream = new DurableStream({ url: "https://streams.example.com/v1/stream/notifications",})const res = await stream.stream({ offset: "-1", live: "long-poll",})res.subscribeJson(async (batch) => { console.log(`Received ${batch.items.length} items`) for (const item of batch.items) { await handleNotification(item) } // Offset is automatically used for next poll})
The subscriber pattern handles backpressure automatically:
const res = await stream.stream({ live: "long-poll",})res.subscribeJson(async (batch) => { // This async function creates natural backpressure // Next batch won't arrive until this completes for (const item of batch.items) { await slowDatabaseWrite(item) } console.log(`Processed batch at offset: ${batch.offset}`)})
If your subscriber function throws an error, the subscription stops. Implement error handling inside the subscriber to continue receiving updates.
Refresh auth tokens automatically for long-running subscriptions:
import { DurableStream } from "@durable-streams/client"const stream = new DurableStream({ url: "https://streams.example.com/v1/stream/events", headers: { // Static header "X-Client-Version": "1.0.0", // Dynamic header - called for each request Authorization: async () => { const token = await getAuthToken() return `Bearer ${token}` }, },})const res = await stream.stream({ live: "long-poll" })// Auth token is automatically refreshed on each pollres.subscribeJson(async (batch) => { // Process items})
Header and param functions are called per-request, not per-session. In long-poll mode, this happens on every poll cycle, allowing fresh tokens to be fetched automatically.
const res = await stream.stream({ live: "long-poll" })res.subscribeJson(async (batch) => { for (const item of batch.items) { await processItem(item) } if (batch.streamClosed) { console.log("Stream closed by writer at offset:", batch.offset) // Clean up resources await cleanup() }})
When a stream is closed, readers receive the Stream-Closed: true header in responses. The streamClosed flag in batches indicates the end of the stream.