No dia 9 de outubro, o time do Deno anunciou que está indo pra Cloudflare. A frase que importa é curta:

We will support the Deno runtime for another year with monthly releases containing bug fixes and security updates. After that year we will end our development of the Deno runtime.

O Deno Deploy ganha mais seis meses. O JSR continua rodando, agora na infraestrutura da Cloudflare. O runtime segue open source, e eles “welcome others who want to continue its development”.

As manchetes chamaram isso de aquisição. Mas leia o post da própria Cloudflare e o runtime do Deno não aparece nenhuma vez. O que a Cloudflare queria era o celld, uma implementação self-hosted da plataforma Workers que o time do Deno lançou dois meses antes.

Eu contribuo com o Node.js, então vou passar pela história toda: de onde o Deno veio, como o Node respondeu aos mesmos problemas, os sinais que apareceram antes do anúncio, o que a Cloudflare está levando e o que fazer se você roda Deno hoje.

1. Onde começou: uma talk sobre arrependimentos

Em 2018, na JSConf EU, o Ryan Dahl deu uma talk chamada 10 Things I Regret About Node.js. Não é todo dia que o criador de um runtime lista, em público, o que errou nele.

A lista incluía:

  • Segurança: qualquer script podia ler seu disco e abrir sockets. Nada pedia permissão.
  • O build system: GYP e o sofrimento dos addons nativos.
  • package.json e node_modules: um sistema de módulos centralizado e um diretório que cresce pra sempre.
  • A mágica da resolução de módulos: require sem extensão, resolução de index.js.
  • Ter largado as promises cedo: as APIs do core baseadas em callback.

No fim da talk ele apresentou um protótipo chamado Deno.

Dois anos depois, em maio de 2020, saiu o Deno 1.0 com esses arrependimentos virados em padrão: seguro por padrão, TypeScript direto, só ES modules, APIs web no lugar das APIs específicas do Node, e um binário único com formatter, linter e test runner dentro.

2. Os mesmos problemas, respostas diferentes

O Ryan não era o único que via esses problemas. Gente de dentro do Node também trabalhou na maioria deles, no próprio ritmo e sob uma restrição que o Deno nunca teve: milhões de aplicações já rodando, que uma release nova não pode quebrar.

Aqui está quando cada runtime lançou a sua resposta:

Problema Deno Node
Restringir o que um script acessa permission flags, 1.0 (2020) permission model experimental na v20.0.0 (2023), estável na v22.13.0 / v23.5.0, --allow-net na v25.0.0
Rodar TypeScript sem build 1.0 (2020) type stripping na v22.6.0 (2024), ligado por padrão na v23.6.0, estável na v25.2.0
fetch global 1.0 (2020) sem flag na v18.0.0 (2022), estável na v21.0.0
Test runner embutido deno test, 1.0 (2020) node:test na v18.0.0, estável na v20.0.0
Watch mode --watch, 1.4 (2020) --watch na v18.11.0 (2022)
Executável único deno compile, 1.6 (2020) Single Executable Applications na v19.7.0 (2023)

As versões do Node vêm da documentação oficial.

O Deno chegou primeiro em todas as linhas. É o que um runtime novo, sem usuário pra proteger, consegue fazer. Mas uma coluna de datas só diz quem chegou primeiro. Não diz por que o outro chegou, e esconde que as respostas são diferentes.

O permission model

O Deno pede que você rode deno run --allow-read --allow-net app.ts. O Node deixa você rodar node --permission --allow-fs-read=./data app.js. Na linha de comando, os dois se parecem.

Por baixo, eles prometem coisas diferentes. O trabalho de segurança do Node sobre carregamento de código vem dos policy manifests experimentais da v11.8.0, em 2019, e o permission model saiu dessa mesma linha de trabalho. A documentação diz com todas as letras o que ele é:

The permission model implements a “seat belt” approach, which prevents trusted code from unintentionally changing files or using resources that access has not explicitly been granted to. It does not provide security guarantees in the presence of malicious code.

É uma escolha de design. O Node confia no código que mandam ele rodar, como diz a security policy, e o permission model existe pra limitar o estrago de erros nesse código. Não é uma sandbox.

TypeScript

O Deno rodava arquivos .ts desde o primeiro dia, compilando.

O Node foi por um caminho mais estreito: type stripping. Ele troca as anotações de tipo por espaço em branco e roda o que sobra. Não tem tsconfig, não tem source map, não tem checagem de tipo, e só sintaxe apagável é permitida. Nada de enum, nada de namespace com código em runtime.

Essa restrição subiu pra linguagem. O TypeScript 5.8 criou a flag --erasableSyntaxOnly justamente pra seu editor avisar quando o código não roda no type stripping do Node. O design do Node mudou o ferramental da própria linguagem.

APIs web

O Deno não inventou o fetch. Quem inventou foi o WHATWG. Mesma coisa pra Web Streams, Web Crypto, WebSocket, structuredClone.

O que o Deno fez foi tornar as APIs do browser a superfície padrão de um runtime de servidor. O Node chegou lá pelo próprio trabalho: o fetch dele roda sobre o undici, um cliente HTTP feito dentro do projeto Node.

E os runtimes não convergem por acaso. Eles sentam na mesma mesa. Node, Deno, Cloudflare Workers e outros começaram a se coordenar no WinterCG, um community group do W3C. Em 2025 esse trabalho foi pra Ecma como TC55, apelidado de WinterTC: um comitê técnico pra runtimes de servidor interoperáveis com a web.

A principal entrega é a Minimum Common API, o pedaço da plataforma web que todo runtime de servidor se compromete a suportar. Quando fetch, URL, TextEncoder ou AbortController se comportam igual no Node e no Deno, não é um runtime copiando o outro. É uma spec que eles escreveram juntos.

Código que roda sem mudança no Node, no Deno, no Bun e no Cloudflare Workers é comum hoje. Em 2018 não era. Todos os runtimes envolvidos, o Node incluso, fizeram parte desse trabalho.

O ferramental

O Deno traz deno test, deno fmt e deno lint num binário só. O Node adicionou test runner e watch mode, e deixou formatação e lint pro ecossistema, onde Prettier, ESLint e Biome já fazem esse trabalho.

Filosofias diferentes. O Deno aposta num binário opinativo. O Node aposta num core pequeno e num ecossistema grande.

O padrão

Olhe os quatro casos juntos. Todas as respostas do Node são opt-in ou não quebram nada. O permission model fica desligado até você passar --permission. O type stripping só roda sintaxe apagável. O fetch chegou do lado do módulo http, não no lugar dele. Ninguém precisou reescrever uma aplicação pra ganhar nada disso. Bastou atualizar.

É a restrição funcionando, e ela também explica por que o produto não sobreviveu.

3. O que não sobreviveu - e o que foi no sentido contrário

Nem toda ideia vingou, inclusive dentro do próprio Deno.

URL imports. O pitch original do Deno era import { serve } from "https://deno.land/std/http/server.ts". Sem package.json, sem node_modules, sem registry.

O Node lançou network imports atrás de uma flag experimental e depois removeu a flag. O próprio Deno adicionou os specifiers npm: em 2022, depois suporte a package.json, depois criou o JSR - que, no fim das contas, é um registry.

Sem node_modules. O Deno 2.0, em 2024, foi em boa parte sobre compatibilidade com o Node: built-ins node:, pacotes npm, package.json, node_modules. Um runtime nascido de uma talk que listava o node_modules como arrependimento acabou suportando ele, porque era lá que os pacotes estavam.

Então as ideias foram nos dois sentidos. O Deno empurrou o ecossistema todo pra padrões web e defaults seguros. O ecossistema do Node puxou o Deno de volta pro npm.

Acredito que esse foi o ponto de virada. Quando seu argumento de venda vira “roda seu código Node, só que melhor”, você está jogando no campo do Node, contra um runtime que continua melhorando por conta própria.

4. Os sinais estavam lá

Nada disso veio do nada. Lido em ordem, o registro público parece uma contagem regressiva lenta.

2023: package.json. O Ryan Dahl teve que explicar em público por que o runtime nascido da talk de arrependimentos estava adotando package.json. O ecossistema tinha ganhado essa discussão.

2025: a infraestrutura encolhe. O Deno Deploy começou em 25 regiões, foi pra 35 e caiu pra 6. A galera percebeu - as regiões, o Fresh sem release desde outubro de 2024, o Deno KV sem versão nova desde 2023. O Ryan respondeu em maio de 2025:

It started in 25 regions, grew to 35, and now runs in 6. That reduction was driven by cost, yes - but also by usage.

No mesmo post, o Deno KV “will remain in beta”, só com correção de bug crítico e de segurança. E a frase final:

We’re not winding down. We’re winding up.

Dezessete meses depois, o time foi pra Cloudflare.

NOTA: todo fundador defende a empresa em público até o dia em que não dá mais. Faz parte do trabalho. Mesmo assim, o corte de custos apareceu no produto muito antes de aparecer no anúncio.

5. O que a Cloudflare está levando de fato

A leitura óbvia é que a Cloudflare contratou um time e matou um concorrente. Acho que isso é meia verdade.

Primeiro, quem encerra o quê. A frase sobre o fim do runtime está no post do Deno. O post da Cloudflare, assinado pelo Kenton Varda e pelo Ryan Dahl, nem menciona o runtime, e nenhum dos dois posts usa a palavra “aquisição”. O time vai. O runtime é o que fica pra trás.

Segundo, o Deno já tinha mudado de rumo antes de tudo isso. Em 5 de agosto de 2026, o time lançou o celld 0.1.0. O Ryan descreve ele como “one binary, written in Rust, with object storage as its only external service dependency”. É uma implementação do modelo de Workers e Durable Objects da Cloudflare que você roda nos seus próprios servidores.

Dois meses antes do anúncio, o produto mais novo do Deno era uma implementação compatível de um produto da Cloudflare. O Kenton Varda explica o interesse do lado da Cloudflare:

Here was an implementation of Workers and Durable Objects designed to be fully compatible with our own, while being focused on being self-hostable and scalable.

Essa era a peça que a Cloudflare não tinha. O workerd, o runtime por baixo do Workers, é open source, mas rodar ele por conta própria nunca foi um caminho oficial. Segundo o post, o Ryan e o Bert Belder vão liderar “a new effort to make workerd self-hosting a first-class supported way to build and run apps using the Workers programming model”, juntando código e ideias do celld no workerd.

Então sim, é uma contratação pra trabalhar no runtime do Workers. A pergunta é por que a Cloudflare quer esse trabalho específico, e o post responde com uma história:

When we originally pitched Workers for Platforms to customers like Shopify in 2022, the feedback was clear. They couldn’t possibly build on us unless the Workers Runtime was open source.

A Cloudflare também encara de frente a acusação de lock-in: “we have former customers that migrated away from us by using workerd. And that’s OK!”

O Shashi Bellamkonda resume o lado do negócio: “Some of Cloudflare’s largest customers have wanted a way to run its software on their own servers”, e “Buyers care about the option to leave.”

Uma plataforma que só roda nos servidores de um fornecedor é difícil de vender pra uma empresa grande. Uma que também roda nas suas máquinas tem uma porta de saída, e porta de saída facilita a entrada. Abrir o código do workerd abriu a porta. O celld é o que torna viável passar por ela.

E o fim do runtime do Deno sai da mesma conta. Um time desse tamanho não consegue manter Deno, Deno Deploy e um workerd self-hosted ao mesmo tempo. Eles escolheram aquilo em que acreditam agora.

Um Worker é uma função que recebe um Request e devolve um Response, as mesmas APIs web que o WinterTC padroniza. O time não troca de caixa de ferramentas, só do produto que constrói com ela.

6. Por que acabou

Imagine um restaurante pequeno que abre numa rua cheia de lugares antigos e conhecidos. Ele tem um cardápio melhor: mais leve, mais limpo, sem aquilo de que todo mundo reclama.

Mas os lugares antigos não estão parados. A clientela deles também vinha pedindo comida mais leve, e as cozinhas começam a mudar, cada uma do seu jeito e no seu ritmo.

O cliente nunca precisa mudar o caminho. A comida melhora no lugar onde ele já vai, com o estacionamento que ele já conhece. O restaurante novo fecha.

Esse é o Deno, e é o padrão da seção 2 visto do outro lado. O custo de trocar de runtime é enorme: dependências, deploy, contratação, anos de memória muscular. Pouquíssimos times pagam esse custo por um default melhor. Eles esperam o default chegar onde já estão.

Tem um segundo motivo, e ele não tem nada a ver com qual runtime é melhor: quem paga cada um.

O Deno era uma empresa. A Deno Land Inc. levantou uma rodada seed e uma série A, e o runtime era de graça. O dinheiro tinha que vir dos produtos em volta: Deno Deploy, Subhosting, Deno KV. É o acordo de sempre de uma startup open source com venture capital. O projeto traz os usuários, e o produto hospedado tem que pagar as contas antes de o investimento acabar.

O Node fica na OpenJS Foundation. Nenhuma empresa é dona dele. Nem sempre foi assim: a Joyent era dona até o fork io.js, em 2014, forçar a ida pra uma fundação no ano seguinte.

Cada modelo compra uma coisa e paga por ela.

O modelo de empresa comprou pro Deno velocidade e coerência. Um time pequeno com uma visão só lançou permissões, TypeScript e APIs web juntos, em 2020, sem pedir licença pra ninguém. O Ryan foi direto no The Changelog em 2024, quando perguntaram por que ele não colocava esse esforço no Node:

I’m not willing to sit in committee for 13 years trying to make [what we built into Deno by default] happen.

O modelo de fundação compra pro Node uma coisa menos empolgante: ele não depende de rodada de investimento. Ninguém pode decidir um dia que acabou. O preço é a velocidade. Toda mudança passa por review e consenso, e tem que cumprir a promessa feita pra quem já roda Node em produção.

Nenhum dos dois modelos conseguiria fazer o trabalho do outro. Uma fundação nunca apostaria num runtime sem node_modules. Uma startup nunca ia segurar um runtime de 17 anos rodando em milhões de servidores sem quebrar nada.

7. O que fazer se você roda Deno hoje

  • Deno Deploy: você tem seis meses. Comece a migração agora. A Cloudflare está oferecendo ajuda pra quem é cliente pago.
  • Runtime do Deno em produção: você tem um ano de correções de segurança. Migre pro Node.
  • Pacotes no JSR: o JSR continua rodando. Por enquanto, tudo certo.
  • Seu código: se você seguiu o estilo do Deno (APIs web, ES modules, TypeScript), a maior parte já roda no Node.

NOTA: node --permission --allow-fs-read=. app.ts roda um arquivo TypeScript sob o permission model, com fetch global e o node --test a um comando de distância. Em 2020, só o Deno rodava algo assim.

O runtime tem mais um ano de correções, e depois acabou. Se você roda Deno, migre pro Node.

Por hoje é só.