On 9 October 2026 Cloudflare announced that the Deno team is joining it, and the coverage since has settled what that means in practice. Development of the standalone Deno runtime stops after a year of monthly maintenance and security releases. Deno Deploy shuts down in six months. JSR, the package registry, carries on under Cloudflare (The New Stack, Runtime Wire).
If you run anything on Deno Deploy, you now have a deadline. This article sorts out what ends and what stays, helps you pick where to move by what your code actually uses, and shows the rewrite for the two likely destinations: Cloudflare Workers and Node.js. It ends with what self-hosted Workers might look like, since that is the project Deno's founders are moving to.
What ends and what stays
The announcements cover some parts of Deno in detail and say nothing about others. Treat a blank in this table as "not announced", not as "safe".
| Part | What happens | Source |
|---|---|---|
| Deno runtime (CLI) | Monthly bug-fix and security releases for one more year, then development stops. Stays MIT-licensed. | The New Stack |
| Deno Deploy | Runs for six more months, then shuts down. Paying customers get help moving to Workers. | Runtime Wire |
| JSR | Keeps running; its infrastructure moves to Cloudflare. | Runtime Wire |
rusty_v8 | Still supported, with work towards using it in workerd. | Runtime Wire |
| celld | Merged into workerd to make self-hosting Workers a supported option. | Cloudflare |
| Deno KV, Fresh | Not addressed in the coverage. | — |
Source: The New Stack (Deno); nodejs.org (Node 26 end of life April 2029); ecorpit.com (Node 24 end of life April 2028)
| Months left | |
|---|---|
| Deno Deploy | 6 months |
| Deno runtime fixes | 12 months |
| Node.js 24 LTS | 18 months |
| Node.js 26 LTS | 30 months |
Six months from 9 October puts the Deploy shutdown around April 2027. Deno's own announcement on deno.com/blog is the place to confirm the exact date, and to check on Deno KV and Fresh before you plan around them.
Why the runtime is ending
Deno shipped in 2018 as Ryan Dahl's second attempt at a server-side JavaScript runtime, with TypeScript, a permission model and web-standard APIs built in. Deno 2, released in October 2024, was mostly about Node.js compatibility (Wikipedia)). That is the problem Dahl points to now: Node adopted native TypeScript, permission controls and web APIs, and the closer Deno got to Node, the more it was maintaining a second implementation of the same thing (The New Stack).
Node now ships most of what made Deno different, so the runtime had less and less of its own to sell.
The contrast with Bun is worth noting. Anthropic bought Bun in December 2025 and committed to keeping it open source; Deno's runtime gets a year of fixes instead (The New Stack). Both runtimes now belong to companies whose main business is something else, and that is a fair input when you choose what to build on next.
Pick a destination by what your code uses
Most Deno Deploy apps are a Deno.serve handler plus a few environment variables, and those move easily to either destination. The decision is made by the parts that are not standard web APIs.
| If your app uses | Move to | Why |
|---|---|---|
Deno.serve, fetch, Web Crypto | Workers or Node | Same Request/Response model on both |
Deno KV with atomic() | Workers + Durable Objects, or Node + a database | Workers KV has no atomic operations |
| Files, subprocesses | Node | node:child_process is a non-functional stub on Workers |
| Your own servers, no vendor | Node now | Self-hosted Workers is not ready yet |
The Workers limits come from Cloudflare's Node.js compatibility page, which lists node:vm and node:child_process as stubs that import but do not work.
Moving a Deploy app to Cloudflare Workers
Workers and Deno Deploy share the same model: a function that takes a Request and returns a Response. The rewrite is mostly the entry point and where configuration comes from.
Swap Deno.serve for a fetch handler
A Worker exports an object with a fetch method. Environment variables arrive as the env argument instead of through Deno.env.
- Deno.serve((req) => {- const url = new URL(req.url);- return new Response(`Hello ${Deno.env.get("NAME")} from ${url.pathname}`);- });+ export default {+ async fetch(req: Request, env: { NAME: string }): Promise<Response> {+ const url = new URL(req.url);+ return new Response(`Hello ${env.NAME} from ${url.pathname}`);+ },+ };Configure it with Wrangler
Set compatibility_date to 2026-08-04 or later and Node.js compatibility is on by default, so code that imports node:buffer or node:crypto keeps working. Earlier dates need the nodejs_compat flag (Cloudflare docs).
{ "name": "my-app", "main": "src/main.ts", "compatibility_date": "2026-08-04", "vars": { "NAME": "k13" }}$ npx wrangler dev$ npx wrangler deployPut secrets in with npx wrangler secret put, not in vars, which is plain configuration checked into your repository.
Deno KV does not map to Workers KV
The names match; the guarantees do not. Deno KV gives you strongly consistent reads by default and transactions through kv.atomic() with .check() on a versionstamp (Deno docs). Workers KV is eventually consistent: a write can take 60 seconds or more to show up in other locations, and Cloudflare says it is not suited to atomic operations (Cloudflare docs).
Read-heavy data that tolerates a minute of staleness, such as feature flags or cached pages, is fine on Workers KV.
Moving to Node.js instead
If you want to run on your own servers, Node is the shortest path, and the gap is much smaller than it was when Deno launched. Node runs .ts files directly: type stripping is on by default from Node 22.18.0 and 23.6.0, and stable from 24.12.0 and 25.2.0 (Node.js docs).
Node only removes type annotations; it does not transform code. That is where Deno code trips:
enum,namespacewith runtime code, and constructor parameter properties throwERR_UNSUPPORTED_TYPESCRIPT_SYNTAX.- Imports need their file extension:
./db.ts, not./db. - Type-only imports need the
typekeyword, or Node tries to load them at runtime. --experimental-transform-typeswas removed in Node 26; usetsxif you depend on enums.
Turn on erasableSyntaxOnly and verbatimModuleSyntax in tsconfig.json and tsc will flag all of these before Node does.
| Deno | Node.js |
|---|---|
Deno.serve(handler) | node:http, or Hono with @hono/node-server |
Deno.env.get("X") | process.env.X |
Deno.readTextFile(path) | readFile(path, "utf8") from node:fs/promises |
npm: specifiers | package.json dependencies |
jsr: specifiers | npx jsr add @scope/pkg (JSR docs) |
--allow-read, --allow-write | --permission with --allow-fs-read, --allow-fs-write |
Write the app once, run it anywhere
If you are not sure where you will end up, put the app behind a framework that runs on all three. Hono supports Workers, Deno, Bun and Node, and only the entry file changes.
import { Hono } from "hono"; export const app = new Hono(); app.get("/", (c) => c.text("ok"));app.get("/hello/:name", (c) => c.json({ hello: c.req.param("name") }));import { app } from "./app.ts"; export default app;import { serve } from "@hono/node-server";import { app } from "./app.ts"; serve({ fetch: app.fetch, port: 3000 });import { app } from "./app.ts"; Deno.serve({ port: 8000 }, app.fetch);Run the Node entry with node src/node.ts on Node 24, and keep the Deno entry working for the next year while you test. On Deno, hono comes from an import map entry in deno.json, such as "hono": "npm:hono" (Hono docs).
What self-hosted Workers might look like
The project Dahl and Bert Belder will lead at Cloudflare is making Workers something you can run on your own machines (Cloudflare). workerd, Cloudflare's open-source runtime, already runs Workers code, but its Durable Objects support is limited to a single instance: fine for local testing, unable to scale across machines (Technobezz). celld, which Deno released in August under Apache-2.0, is the missing layer.
As described in Xenospectrum's write-up of celld v0.1.0, an app is split into named "cells", each a single-threaded V8 isolate with its own SQLite database. One node owns a cell at a time, and ownership is recorded in a shared object-storage bucket using conditional writes, with an epoch number to fence out an old owner after a failover. State is replicated to the bucket, so another node can restore a cell if its host dies. Every durable write waits for at least one bucket round trip.
Cloudflare has said more details will follow over the coming months. Until there is a merged, documented release, plan your move around Workers or Node, not around this.
What to do this week
- List every app on Deno Deploy, with an owner and a target: Workers or Node.
- Search each codebase for
Deno.openKvand.atomic(). Those are the parts that need a real design, not a rename. - Search for
Deno.calls and map each one with the table above. - Move the entry point behind Hono or a plain fetch handler, so the destination is a one-file change.
- Pin your Deno version in CI for the year of maintenance releases, and set a reminder for when they stop.
- Check deno.com/blog for the exact Deploy shutdown date and for news on Deno KV and Fresh.
If you only do one thing, do the KV search. Everything else is a rename; a lost atomic check is a bug you will find in production.