The Deno Team Joins Cloudflare: A Promise Is Not an Exit Plan

The Deno Team Joins Cloudflare: A Promise Is Not an Exit Plan

On 9 October 2026, Deno announced that "the entire Deno team is joining Cloudflare." The post came from Ryan Dahl, who created Deno and, before that, Node.js. Neither company disclosed a price or terms. Both describe it as the team "joining" Cloudflare, and Cloudflare's own post says the aim is "to radically simplify self-hosting Workers and Durable Objects so developers can use the same primitives in more places."

The practical changes are easy to list. Deno Deploy, Deno's hosted platform, "will continue operating for six months before shutting down," with migration help for paying customers moving to Cloudflare Workers. The Deno runtime gets another year of monthly bug-fix and security releases, and then Deno ends its development, though the code stays open source. For anyone who runs servers, the interesting part is not who joined whom. It is that a promise not to strand you is exactly that: a promise.

What vendor lock-in actually is

Lock-in is rarely a plot. Usually it is four ordinary things stacked together: a service you do not control, data you cannot easily export, an API with no open equivalent, and a product roadmap that belongs to someone else. Any one of them is manageable. All four together mean that when the roadmap changes, your plans change with it.

Cloudflare has a real answer to this, and it deserves a fair hearing. In Cloudflare's post, Kenton Varda points out that workerd, the Cloudflare Workers runtime, is open source, "the same code we run in production," and that some former customers have used it to migrate away from Cloudflare. He explicitly rejects the idea that the company depends on lock-in. That is more than most platforms offer.

The irony is still hard to miss. The company making the strongest "this is not lock-in" argument is the same one whose move gives Deno Deploy a shutdown date and ends independent development of the Deno runtime. Nobody acted in bad faith here. The people who own the products made a product decision, which is exactly how hosted services work.

So look at the shape of the argument. It describes an exit that exists. Whether that exit works for you depends on whether your code, your data and your dependencies fit through it, and you only learn that by walking through it. An escape hatch you have never tested is not an escape hatch. It is a door you are assuming will open.

The exit path you can actually test

These are the four checks I run before I let anything become load-bearing in my own stack. You can run all four this week.

1. The licence

Open the repository and read the LICENSE file, not the marketing page. A permissive licence such as MIT or Apache-2.0 means you can fork, patch and self-host without asking anyone. A copyleft licence such as the AGPL also lets you self-host, with conditions on sharing your changes. Be careful with "source-available" licences that restrict commercial or hosted use, and read the actual terms. For a GitHub project:

gh api repos/OWNER/REPO/license --jq .license.spdx_id

If that returns an error or NOASSERTION, read the file by hand.

2. The data

Ask two questions. Can you export everything in an open, documented format? And have you ever actually done a full export? The second one matters more. For a Postgres-backed app, a real test is a dump followed by a restore into a throwaway container:

pg_dump --format=custom --file=app.dump "$DATABASE_URL"
docker run -d --name restore-test -e POSTGRES_PASSWORD=test postgres:16
sleep 10
docker cp app.dump restore-test:/tmp/app.dump
docker exec restore-test pg_restore -U postgres -d postgres --no-owner /tmp/app.dump

Use the same major Postgres version you run in production, then count the rows in your largest tables and compare. For object storage, rclone sync remote:bucket ./bucket-copy followed by rclone size on both sides tells you whether you really have everything. If the vendor's only export is a CSV of some tables or a "contact support" link, that is your answer.

3. The API surface

The cheapest migration is the one where you change a hostname instead of rewriting code. That only happens when the API you depend on has an open equivalent: S3-compatible object storage, standard SQL, SMTP for sending mail and IMAP for reading it. Point your S3 client at a local MinIO or Garage instance, or swap SMTP_HOST in your .env for a test relay, and see what breaks.

aws s3 ls s3://my-bucket --endpoint-url http://localhost:9000

When the only client for a feature is the vendor's own SDK, with no open protocol underneath, write that down. That is the part of your migration that turns into a rewrite.

4. The runtime

The last check is whether the same code runs somewhere that is not the vendor's platform. Take a spare machine or a cheap VPS, give it no vendor credentials, and try to start the app with docker compose up, deno run, node server.js or, for Workers code, workerd serve config.capnp. A runtime is only one part of a platform. The queues, key-value stores and databases around it are the other part, so note every call that fails because a managed service is missing.

I wrote about the same trap from another angle in renting a dependency someone else controls.

The worked example: what survives the Deno move

Take today's announcement apart and sort it into what is hosted and what is open. Deno Deploy is a hosted service. It gets six months, and then it stops. Paying customers get migration support to Cloudflare Workers, which is helpful, but the destination is chosen for you. If you built on Deno Deploy, your exit was always going to be someone else's decision.

The Deno runtime is open source. It gets a year of monthly releases with bug fixes and security updates, and after that Deno ends its development. The code does not disappear. Deno says the runtime "will remain open source" and welcomes others who want to continue its development. The code you wrote for it will still run on your own machine the day after the last release.

JSR, the JavaScript package registry, keeps operating, with its infrastructure moving to Cloudflare. Cloudflare also says it will keep supporting rusty_v8 and work toward integrating it into workerd.

So what survives is exactly what was open. The hosted platform gets a shutdown date, and the published code stays published. A hosted service is a promise that its owner can revise, while open source, once published, can be abandoned but never un-published. I made a similar point about a hosted service someone else can switch off. This is the same pattern with a bigger name attached.

There is an uncomfortable half, and it is worth saying plainly. Open source that nobody maintains does not shut down with an email. It just stops improving. Security fixes stop, new operating system and dependency versions go untested, and the cost of running it safely slowly moves onto you. A year of maintenance is real time to plan, not a guarantee that the plan will be easy.

The honest limits of self-hosting

Self-hosting is not free, and it is not always possible. When you run something yourself, you take on its patch cadence, its backups, its availability and its on-call. If a serious vulnerability is published on a Sunday, you are the one reading the advisory. I run my own stack because I like that trade, not because it costs nothing.

Some things are genuinely hard to replace. A global anycast network, large-scale DDoS absorption and a well-run managed database with point-in-time recovery are serious engineering, and paying for them is often the right call. The goal is not to avoid every vendor. It is to know, for each vendor, what you would do if it changed its mind.

A fork is only alive if someone maintains it. "We can always fork it" is true and useful, but it is only a plan if you can name who would do the work, or if you are willing to pin a version and accept that it will stop improving.

The practical version of all this is boring. Keep a short file, something like EXIT.md, in each project. List every external dependency, its licence, how you export its data and the date you last tested that export. Review it whenever news like today's lands.

Start with one dependency

Pick the one service your project would miss most and run the four checks against it this week. If the export works and the code runs elsewhere, you have an exit. If it does not, you have a list.

If you would rather have someone map the exit path through your stack with you, that is the kind of work I take on. Details are on the services page. Fiverr: hiteshsaini459 · Upwork: hiteshsaini25.