{"slug": "show-hn-durable-actors-oss-durable-objects-with-configurable-compute", "title": "Show HN: Durable Actors – OSS Durable Objects with configurable compute", "summary": "TerseAI released Durable Actors, an open-source alternative to Cloudflare Durable Objects that provides stateful serverless functions with durable state and serialized execution, self-hostable on GCP with no vendor lock-in. The runtime supports Python and TypeScript clients, requires Node.js 22.19+ and Bun 1.3.9+, and is aimed at real-time applications such as chat systems, collaboration tools, and agent swarms.", "body_md": "*an open-source alternative to Cloudflare Durable Objects... with no vendor lock-in, memory limits, and observability built in.*\n\nDurable Actors help you **build real-time applications** like chat systems (e.g. ChatGPT, Codex), collaboration tools (e.g. Notion), and agent swarms (e.g. Devin).\n\nThey provide *stateful serverless functions*, a foundational building block that abstracts away persistence, coordination, and infrastructure challenges in distributed systems.\n\n[Live demo](https://demo.useterse.ai) · [TypeScript documentation](https://github.com/TerseAI/durable-actors/blob/main/docs/reference/typescript-guide.md) · [Python documentation](https://github.com/TerseAI/durable-actors/blob/main/docs/reference/python-guide.md)\n\n1. Define an *actor* , a class with*durable state* (i.e. data survives interruptions, errors, and restarts) and*serialized execution* (i.e. concurrent callers can update it safely).\nFor example:\n\n- **If you were building ChatGPT...** a chat actor can store conversations that survive LLM flakiness and server crashes (durable state)\n- **If you were building Notion...** a document actor can coordinate concurrent edits from several people and agents (serialized execution)\n\n1. Generate type-safe clients automatically with the Durable Actors SDK. For now, it supports Python and TypeScript.\n2. Develop locally with one command and later [self-host the Durable Actors runtime on GCP](https://github.com/TerseAI/durable-actors/blob/main/docs/self-hosting.md) .\n\nInstall Node.js 22.19+ and Bun 1.3.9+.\n\n```\nnpx durable-actors init my-actors\ncd my-actors\nnpm install\nnpx durable-actors dev # Run the server locally on your machine\n```\n\nDefine and export actors in your actor project’s `src/actors.ts`, the default entrypoint loaded by `durable-actors dev`. The runtime loads actors on demand and persists fields marked `@Persisted`.\n\nFor example, a chat history actor:\n\n``` js\nimport { openai } from \"@ai-sdk/openai\"\nimport { streamText } from \"ai\"\nimport { Actor, type ActorSocket, Interleave, Persisted } from \"durable-actors\"\n\ntype Message = { role: \"user\" | \"assistant\"; content: string }\n\nexport class ChatHistory extends Actor<null, string, Message[]> {\n    @Persisted messages: Message[] = []\n\n    async onConnect(socket: ActorSocket<null, Message[]>) {\n        socket.send(this.messages)\n    }\n\n    @Interleave // Let other calls run during await, e.g. new connections while a reply streams.\n    async onMessage(_socket: ActorSocket<null, Message[]>, text: string) {\n        this.messages.push({ role: \"user\", content: text })\n        const result = streamText({ model: openai(\"gpt-5-mini\"), messages: [...this.messages] })\n        const reply: Message = { role: \"assistant\", content: \"\" }\n        this.messages.push(reply)\n        this.broadcast(this.messages)\n        for await (const chunk of result.textStream) {\n            reply.content += chunk\n            this.broadcast(this.messages)\n        }\n    }\n}\n```\n\nWe make it super easy to integrate the actors into your existing tech stack. Just generate the client and you get a fully type safe contract to interact with.\n\n```\nnpx durable-actors generate\n```\n\nCreate a WebSocket connection to one shared chat:\n\n``` python\nimport express from \"express\"\n\nimport { actors } from \"../generated/index.js\"\n\nexport const app = express()\n\napp.post(\"/api/chat/socket\", async (_req, res) => {\n    const grant = await actors.ChatHistory.prepareWebsocket({\n        actorId: \"lobby\",\n        metadata: null\n    })\n    res.set(\"Cache-Control\", \"no-store\").json(grant)\n})\njs\nimport { useEffect, useRef, useState } from \"react\"\nimport { createRoot } from \"react-dom/client\"\n\nimport type { actors } from \"../generated/index.js\"\n\nfunction Chat() {\n    const socket = useRef<WebSocket>(null)\n    const [messages, setMessages] = useState<actors.ChatHistory.Outgoing>([])\n\n    useEffect(() => {\n        let active = true\n        async function connect() {\n            const response = await fetch(\"/api/chat/socket\", { method: \"POST\" })\n            const { websocketUrl } = await response.json()\n            if (!active) return\n            socket.current = new WebSocket(websocketUrl)\n            socket.current.onmessage = event => setMessages(JSON.parse(event.data))\n        }\n        void connect()\n        return () => {\n            active = false\n            socket.current?.close()\n        }\n    }, [])\n\n    function send(form: FormData) {\n        const text = String(form.get(\"message\")).trim()\n        if (!text || socket.current?.readyState !== WebSocket.OPEN) return\n        socket.current.send(JSON.stringify(text))\n    }\n\n    return (\n        <main>\n            <div role=\"log\" aria-label=\"Messages\">\n                {messages.map((message, index) => (\n                    <p key={index}><strong>{message.role}:</strong> {message.content}</p>\n                ))}\n            </div>\n            <form action={send}>\n                <input name=\"message\" aria-label=\"Message\" required />\n                <button>Send</button>\n            </form>\n        </main>\n    )\n}\n\ncreateRoot(document.getElementById(\"root\")!).render(<Chat />)\n```\n\nFor a complete app with error handling and retries, see the [AI Chat example](https://github.com/TerseAI/durable-actors/blob/main/examples/ai-chat).\n\nDurable Agents provides built-in observability features:\n\nFor complete sample applications, see [AI Chat](https://github.com/TerseAI/durable-actors/blob/main/examples/ai-chat), [Collaborative Documents](https://github.com/TerseAI/durable-actors/blob/main/examples/documents), and [Chatroom](https://github.com/TerseAI/durable-actors/blob/main/examples/chat).\n\nBug reports, feature requests, documentation fixes, and code contributions are welcome. See the [contributing guide](https://github.com/TerseAI/durable-actors/blob/main/CONTRIBUTING.md) for repository setup and checks, and follow our [code of conduct](https://github.com/TerseAI/durable-actors/blob/main/CODE_OF_CONDUCT.md).\n\nUse [GitHub Issues](https://github.com/TerseAI/durable-actors/issues) for bugs, ideas, and questions. Report vulnerabilities privately using our [security policy](https://github.com/TerseAI/durable-actors/blob/main/SECURITY.md).\n\nFollow development and release notes on [GitHub Releases](https://github.com/TerseAI/durable-actors/releases).\n\n[MIT](https://github.com/TerseAI/durable-actors/blob/main/LICENSE.md) © 2026 Terse", "url": "https://wpnews.pro/news/show-hn-durable-actors-oss-durable-objects-with-configurable-compute", "canonical_source": "https://github.com/TerseAI/durable-actors", "published_at": "2026-10-06 15:58:19+00:00", "updated_at": "2026-10-07 17:18:26.245895+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-infrastructure", "ai-tools"], "entities": ["TerseAI", "Durable Actors", "Cloudflare Durable Objects", "GCP", "Node.js", "Bun", "Python", "TypeScript"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-durable-actors-oss-durable-objects-with-configurable-compute", "markdown": "https://wpnews.pro/news/show-hn-durable-actors-oss-durable-objects-with-configurable-compute.md", "text": "https://wpnews.pro/news/show-hn-durable-actors-oss-durable-objects-with-configurable-compute.txt", "jsonld": "https://wpnews.pro/news/show-hn-durable-actors-oss-durable-objects-with-configurable-compute.jsonld"}}