[{"data":1,"prerenderedAt":48},["ShallowReactive",2],{"\u002Fcloudflare-config\u002Fdurable-objects":3},{"title":4,"description":5,"path":6,"date":7,"updated":8,"verified":7,"category":9,"keywords":10,"officialSources":16,"related":26,"readingTime":30,"html":31,"toc":32},"Durable Objects in cloudflare.config.ts","Declare the exported class and its storage, then bind to that class. A Durable Object needs both a lifecycle declaration and application code.","\u002Fcloudflare-config\u002Fdurable-objects","2026-09-29","2026-09-30","Configuration",[11,12,13,14,15],"cloudflare.config.ts durable objects","cf durable objects config","cloudflare exports durableObject","durable object binding cloudflare.config.ts","worker.exports durableObject",[17,20,23],{"label":18,"url":19},"Cloudflare configuration types and helpers","https:\u002F\u002Fgithub.com\u002Fcloudflare\u002Fworkers-sdk\u002Ftree\u002Fmain\u002Fpackages\u002Fconfig\u002Fsrc",{"label":21,"url":22},"Durable Object class exports and migrations","https:\u002F\u002Fdevelopers.cloudflare.com\u002Fdurable-objects\u002Freference\u002Fdurable-objects-migrations\u002F",{"label":24,"url":25},"cf CLI source and README","https:\u002F\u002Fgithub.com\u002Fcloudflare\u002Fcf\u002Ftree\u002Fmain\u002Fpackages\u002Fcli",[27,28,29],"\u002Fcloudflare-config","\u002Fcloudflare-config\u002Fkv","\u002Fwrangler-to-cf",2,"\u003Ch2 id=\"quick-configuration\">Quick configuration\u003C\u002Fh2>\n\u003Cdiv class=\"code-block\">\u003Cdiv class=\"code-toolbar\">\u003Cspan>cloudflare.config.ts\u003C\u002Fspan>\u003Cbutton type=\"button\" data-copy-code aria-label=\"Copy code\">Copy\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre>\u003Ccode class=\"hljs language-ts\">\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { bindings, defineConfig, \u003Cspan class=\"hljs-built_in\">exports\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;cf\u002Fconfig&quot;\u003C\u002Fspan>;\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">default\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">defineConfig\u003C\u002Fspan>({\n  \u003Cspan class=\"hljs-attr\">worker\u003C\u002Fspan>: {\n    \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;counter-worker&quot;\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-attr\">compatibilityDate\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;2026-09-29&quot;\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-attr\">entrypoint\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;.\u002Fsrc\u002Findex.ts&quot;\u003C\u002Fspan>,\n    \u003Cspan class=\"hljs-attr\">exports\u003C\u002Fspan>: {\n      \u003Cspan class=\"hljs-title class_\">Counter\u003C\u002Fspan>: \u003Cspan class=\"hljs-built_in\">exports\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">durableObject\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">storage\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;sqlite&quot;\u003C\u002Fspan> }),\n    },\n    \u003Cspan class=\"hljs-attr\">env\u003C\u002Fspan>: {\n      \u003Cspan class=\"hljs-attr\">COUNTERS\u003C\u002Fspan>: bindings.\u003Cspan class=\"hljs-title function_\">durableObject\u003C\u002Fspan>({\n        \u003Cspan class=\"hljs-attr\">worker\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;counter-worker&quot;\u003C\u002Fspan>,\n        \u003Cspan class=\"hljs-attr\">exportName\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&quot;Counter&quot;\u003C\u002Fspan>,\n      }),\n    },\n  },\n});\n\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cp>This declares a new SQLite-backed class named \u003Ccode>Counter\u003C\u002Fcode> and gives the same Worker a \u003Ccode>COUNTERS\u003C\u002Fcode> binding. The Worker name in the binding matches the Worker that exports the class.\u003C\u002Fp>\n\u003Ch2 id=\"two-declarations-two-purposes\">Two declarations, two purposes\u003C\u002Fh2>\n\u003Cp>\u003Ccode>worker.exports.Counter\u003C\u002Fcode> describes the class’s storage and deployment lifecycle. \u003Ccode>worker.env.COUNTERS\u003C\u002Fcode> connects application code to the class namespace. Neither declaration implements the class itself.\u003C\u002Fp>\n\u003Cp>The current helper takes \u003Ccode>exportName\u003C\u002Fcode>; do not copy Wrangler’s \u003Ccode>class_name\u003C\u002Fcode> into it. Use the \u003Ca href=\"\u002Fcloudflare-config-builder\">config builder\u003C\u002Fa> to generate both declarations together for a new class.\u003C\u002Fp>\n\u003Ch2 id=\"export-the-class-from-your-source\">Export the class from your source\u003C\u002Fh2>\n\u003Cdiv class=\"code-block\">\u003Cdiv class=\"code-toolbar\">\u003Cspan>src\u002Findex.ts\u003C\u002Fspan>\u003Cbutton type=\"button\" data-copy-code aria-label=\"Copy code\">Copy\u003C\u002Fbutton>\u003C\u002Fdiv>\u003Cpre>\u003Ccode class=\"hljs language-ts\">\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { \u003Cspan class=\"hljs-title class_\">DurableObject\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&quot;cloudflare:workers&quot;\u003C\u002Fspan>;\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">class\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Counter\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">extends\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_ inherited__\">DurableObject\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">increment\u003C\u002Fspan>(): \u003Cspan class=\"hljs-title class_\">Promise\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-built_in\">number\u003C\u002Fspan>&gt; {\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> count = (\u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-variable language_\">this\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">ctx\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">storage\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">get\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-built_in\">number\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&quot;count&quot;\u003C\u002Fspan>) ?? \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>) + \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>;\n    \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-variable language_\">this\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">ctx\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">storage\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">put\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;count&quot;\u003C\u002Fspan>, count);\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> count;\n  }\n}\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">default\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">fetch\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">_request\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Request\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">env\u003C\u002Fspan>: {\n    COUNTERS: DurableObjectNamespace&lt;Counter&gt;;\n  }\u003C\u002Fspan>) {\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> stub = env.\u003Cspan class=\"hljs-property\">COUNTERS\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">getByName\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&quot;shared-counter&quot;\u003C\u002Fspan>);\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> count = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> stub.\u003Cspan class=\"hljs-title function_\">increment\u003C\u002Fspan>();\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Response\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">json\u003C\u002Fspan>({ count });\n  },\n};\n\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cp>Generate the Cloudflare runtime types in your Worker project. This minimal example uses one named object; choose object identities around your application’s isolation needs.\u003C\u002Fp>\n\u003Ch2 id=\"migrating-an-existing-class\">Migrating an existing class\u003C\u002Fh2>\n\u003Cp>The new exports model can describe class creation, deletion, renaming and transfer. Existing state must be preserved intentionally. Do not turn every old class into a newly declared class or change its storage backend merely because the example uses SQLite.\u003C\u002Fp>\n\u003Cp>Use \u003Ca href=\"\u002Fwrangler-to-cf\">cf migrate\u003C\u002Fa> and review the class name, owning Worker, storage and lifecycle against the original configuration. Consult the official class export documentation before a rename or transfer.\u003C\u002Fp>\n\u003Ch2 id=\"common-mistakes\">Common mistakes\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>Adding only the binding and omitting the exported class declaration.\u003C\u002Fli>\n\u003Cli>Declaring \u003Ccode>Counter\u003C\u002Fcode> while the source exports a differently named class.\u003C\u002Fli>\n\u003Cli>Referencing another Worker unintentionally through the binding’s \u003Ccode>worker\u003C\u002Fcode> field.\u003C\u002Fli>\n\u003Cli>Treating storage backend changes as a harmless configuration rename.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Read the \u003Ca href=\"\u002Fcloudflare-config\">configuration guide\u003C\u002Fa> for binding structure or the \u003Ca href=\"\u002Fcloudflare-config\u002Fkv\">KV comparison\u003C\u002Fa> when deciding whether your state needs coordination.\u003C\u002Fp>\n",[33,36,39,42,45],{"id":34,"text":35},"quick-configuration","Quick configuration",{"id":37,"text":38},"two-declarations-two-purposes","Two declarations, two purposes",{"id":40,"text":41},"export-the-class-from-your-source","Export the class from your source",{"id":43,"text":44},"migrating-an-existing-class","Migrating an existing class",{"id":46,"text":47},"common-mistakes","Common mistakes",1790729614466]