Get in touch

Get in touch with Binary

Binary Studio website uses cookies to enhance your browsing experience. By continuing to use our site, you agree to our Privacy Policy and use of cookies.

Learn more more arrow
Vladyslav Zubko 05.10.2021

The product owner comes and says: We need to rewrite everything from Node to Deno…

Let's start with the riddle, who is shown in this photo?

Ryan Dahl, deno, node.js

Most likely, you have worked with his product. 


Ryan Dahl is a software engineer and the original developer of the Node.js (~2009 year). In January 2012, Dahl announced that he turned over the reins to NPM creator.

In 2018 he made a presentation 10 things I regret about Node.js at the JSConf conference. Also, at this presentation, he announced Deno — a secure runtime for JavaScript and TypeScript.

In this article, we will take a look at Deno and how it compares to Node.js to help understand what they have in common, how they differ and is it real that Deno will kill Node.js?


Let's imagine a situation: A product owner comes to us and tells us to rewrite the project from Node to Deno.

But why? Who knows, it’s just an example. 

For now, let's imagine that there is no other way around this decision and we need to do it. But then what? Do we really need to rewrite most of the code in the project?

Let's check this with an example of a small project.

Project structure


Root file

Nothing special. The project is written using a node-framework - Koa (next generation of the Express node-framework).

What it can do:

  • Serve static content
  • Has a books CRUD api (all data is stored in the json format).

That's all. Perfect!

Let's move on to the most interesting part.

From Node to Deno

Before we start, let's take a look at the definition of these two technologies that we can find on the technology homepage.

Node — is a JavaScript runtime.

Deno — is a secure runtime for JavaScript and TypeScript.

Both definitions contain runtime and JavaScript. Does it mean that we can run the same code on both platforms? Not at all.

Let's try to run the code that we wrote on NodeJS base using Deno (if you don't have Deno installed yet, you can find how to do it here):

Aaaand we get an error:

But interestingly, we did not receive an error saying that we use TypeScript code. This is because Deno supports TypeScript out of the box!

If we tried to run code written with TypeScript in NodeJS without using ts-node (or any other additional package), we would immediately get errors about the unknown syntax.

Okay, let's try to fix the differences between Node and Deno.

First of all, let's install an official extension to help us develop on Deno and add this to the editor settings:

Then, let's remove the things that are completely useless for Deno that are in NodeJS.

Stop what? Where do we store our packages now?

Do not worry, we will store the dependencies we need here:

Two questions immediately arise: what is dependencies.ts and why do we use a link to import packages?

Let's start from the end. Two reasons that Ryan talked about in his presentation and that he tried to fix this in Deno are node_modules and package.json.



  • Allow Node's require() to inspect package.json files for "main";
  • Included NPM in the Node distribution, which much made it the defacto standard;
  • It's unfortunate that there is centralized (privately controlled even) repository for modules;
  • Allowing package.json gave rise to the concept of a "module" as a directory of files;
  • This is no a strictly necessary abstraction - and one that doesn't exist on the web;
  • package.json now includes all sorts of unnecessary information. License? Repository? Description? It's boilerplate noise;
  • If only relative files and URLs were used when importing, the path defines the version. There is no need to list dependencies.


  • It massively complicates the module resolution algorithm;
  • vendored-by-default has good intentions, but in practice just using $NODE_PATH wouldn't have precluded that;
  • Deviates greatly from browser semantics;
  • It's my fault and I'm very sorry;
  • Unfortunately it's impossible to undo now.

(The reasons are taken from Dahl's presentation). When the program is launched for the first time, modules are downloaded and cached in the system. And when reused, they will be taken from there. While reusing modules, they will be taken from the cache.

Now about dependencies.ts. It's just a file that I created to store all third-party project's dependencies (the name can be whatever). Third-party modules can be included in any part of the program but this is not a good practice. It is better to keep all the modules in one place.

Let's try to run the code again. We get the following error:

On the sixth line we have this:

Everything looks fine. What is the problem?

It would seem that we can miss the file name if the file is called index.

This is possible but only in NodeJS. In Deno we must always explicitly specify the file with its extension.

These are two more things Dahl regrets about Node:


  • I thought it was cute because there was index.html;
  • It needlessly complicated the module loading system;
  • It became especially unnecessary after require supported package.json.

modules without the extension:

  • Needlessly less explicit;
  • Not how browser JavaScript works. You cannot omit the .js in a script tag src attribute;
  • The module loader has to query the file system at multiple locations trying to guess what the user intended.

Let's fix this and a few other errors that we will run into.

  1. Resole magic names

2. Resolve magic variables/functions/modules that are only available in Node

3. Resolve take variables from env

4. Resolve writeFile/readFile helpers

5. Resolve Paths

6. Fetch out of the box

Of course there were more changes, but these are the most interesting things that deserve attention.

Root file using Deno

Almost the same, isn't it? 


Finally, let's run our refactored app!

We are still getting the error:

But this time it is an error that was not received before.

Another issue which Ryan regrets is security in NodeJS:

  • V8 by itself is a very good security sandbox;
  • Had I put more thought into how that could be maintained for certain applications, Node could have had some nice security guarantees not available in any other language;
  • Example: Your linter shouldn't get complete access to your computer and network.

Every time we run a program on Deno, we need to specify the appropriate permissions that it will possess.

To run our app we need to use these permissions:

By this link you can find a list of all permissions.

Let's try to run it again:

Let's try to call the APIs:

Everything works! 

But look at the code differences:

development to staging, deno

Amazing, isn't it?

Okay-okay, most of the changes (almost all) are due to dependencies, since now we only have 2 dependencies.

Easter eggs

Do you like easter eggs? Hope so ?

Let's see something:

Not sure if this was done on purpose (I hope so), but there is something similar here, isn't there? 

(There are a number of other packages that are named similarly.)


Until recently Node had almost no competitors (io.js ?) and was almost the only platform where we could run JavaScript on the server.

But now, Node has a worthy competitor, Deno — a secure runtime for JavaScript and TypeScript, who will step on its heels every day.

Competition is usually always good!

This article does not cover all topics such as code lintingcode formattingcode testing, etc. By the way, most of these things Deno has out of the box ?

There is no need to run and rewrite everything but at least everyone should take a look and try Deno. People who have already worked with Node shouldn't take a lot of effort to make friends with this beautiful technology.