---
changelog:
  category: Release
  version: 1.9.0
date: '2025-09-23T11:53:15Z'
seo:
  description: >-
    Durable Iterator is a complete rewrite of the old Durable Event Iterator. It
    builds on Event Iterator by offloading streaming to a dedicated service
    that…
title: v1.9.0
type: changelog
---
### Durable Iterator [docs](https://orpc.dinwwwh.com/docs/integrations/durable-iterator)

**Durable Iterator** is a complete rewrite of the **old Durable Event Iterator**. It builds on [Event Iterator](https://orpc.dinwwwh.com/docs/event-iterator) by offloading streaming to a dedicated service that delivers durable event streams with automatic reconnections and event recovery.
 
> [!NOTE]
> While not limited to [Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/), it's currently the only supported implementation.

#### Durable Object

```ts
import { DurableIteratorObject } from '@orpc/experimental-durable-iterator/durable-object'

export class ChatRoom extends DurableIteratorObject<{ message: string }> {
  constructor(ctx: DurableObjectState, env: Env) {
    super(ctx, env, {
      signingKey: 'secret-key', // Replace with your actual signing key
      interceptors: [
        onError(e => console.error(e)), // log error thrown from rpc calls
      ],
      onSubscribed: (websocket, lastEventId) => {
        console.log(`WebSocket Ready id=${websocket['~orpc'].deserializeId()}`)
      }
    })
  }

  someMethod() {
    // publishEvent method inherited from DurableIteratorObject
    this.publishEvent({ message: 'Hello, world!' })
  }
}
```

#### Server Side

```ts
import { DurableEventIterator } from '@orpc/experimental-durable-iterator'

export const router = {
  onMessage: base.handler(({ context }) => {
    return new DurableEventIterator<ChatRoom>('some-room', {
      tags: ['tag1', 'tag2'],
      signingKey: 'secret-key', // Replace with your actual signing key
    })
  }),

  sendMessage: base
    .input(z.object({ message: z.string() }))
    .handler(async ({ context, input }) => {
      const id = context.env.CHAT_ROOM.idFromName('some-room')
      const stub = context.env.CHAT_ROOM.get(id)

      await stub.publishEvent(input)
    }),
}
```

#### Client Side

```ts
const iterator = await client.onMessage()

for await (const { message } of iterator) {
  console.log('Received message:', message)
}

await client.sendMessage({ message: 'Hello, world!' })
```

### `experimental_streamedOptions` is removed in old tanstack query

If you depend on this, please try [NEW Tanstack Query Interagration](https://orpc.dinwwwh.com/docs/integrations/tanstack-query)

---

> [!TIP]
> If you find oRPC valuable and would like to support its development, you can do so [here](https://github.com/sponsors/dinwwwh).

### &nbsp;&nbsp;&nbsp;🚀 Features

- **durable-iterator**:
  - Rewrite + enchance &nbsp;-&nbsp; by @dinwwwh in https://github.com/middleapi/orpc/issues/965 [<samp>(c5401)</samp>](https://github.com/middleapi/orpc/commit/c5401b5e)
  - Rewrite + enhance (part 2) &nbsp;-&nbsp; by @dinwwwh [<samp>(03cef)</samp>](https://github.com/middleapi/orpc/commit/03cefb3e)
- **tanstack-query**:
  - Update to 5.89 with `streamOptions` update &nbsp;-&nbsp; by @dinwwwh in https://github.com/middleapi/orpc/issues/1019 [<samp>(b83dc)</samp>](https://github.com/middleapi/orpc/commit/b83dcee5)

##### &nbsp;&nbsp;&nbsp;&nbsp;[View changes on GitHub](https://github.com/middleapi/orpc/compare/v1.8.9...v1.9.0)
