Node.js built-ins on Deno Deploy
If there's any demand at all for doing what the feature does, then devs will tend to write polyfills to make the feature "work" (for some value of "work") in the other engines, so that their code can still be "portable" (i.e. at least not crash) despite calling the feature. Also, eventually, the other engines might introduce their own versions of the feature, with their own APIs, for the polyfill to fill over; and then even more eventually, those will get standardized.
If there's a huge demand for the feature (think: XMLHTTPRequest), then other engines will rush to just clone the feature's API as-is, so that their engine won't be held back by the lack of it, or by the bad performance of a polyfill solution.
Also FWIW, all of these various runtimes are starting to converge on a single spec so they are interoperable and your code is truly portable — https://wintercg.org/
Having a feature is not the same thing as having API compatibility with Node's implementation of the feature. I think people are worried that an exciting project that aimed to have a different approach and a different set of trade-offs from Node will end up having to support everything that Node does, possibly inheriting its trade-offs and losing the freedom to innovate that they started with.
Even if there's no technical trade-off, it does seem that most of their engineering efforts will be focused on backwards compatibility with Node, instead of the new vision that they were promising.
I’ve seen this type of thing in vanilla js vs react projects. Where there was a fine vanilla js implementation, but it was abandoned by maintainers to do a react version.
Or a new frontend package is built for react by default rather than vanilla js, (or a very light set of js dependencies) even if it easily could have been.
And my experience is that react has been corruptive to the vanilla js ecosystem as a result.
It’s a bit of a reverse from node->deno but I could easily see how deno would be stunted or affected in an unknown but possibly not great way by this.
All that said, Deno has had to pivot because node seems to have gotten its act together to some extent. At least compared to when Deno set out.
So as a practical user acquisition need, not want but need, Deno had no choice but to do this. And the decision to go down this path was made quite a while back, iirc.
I remain hopeful for Deno and the team behind it. Frontend tech is very competitive.
The thrashing across the frontend stack that backend folks recoil from has made things stronger and there’s a lot of talent at work.
I think that most wanting to use Deno are wanting to write an application in a more Deno friendly way. Linting, formating, and typescript in the box. But pragmatically also needing or desiring to be able to utilize existing NPM modules. Those NPM modules more often than not needing node compatibility.
It doesn't mean the application at its core will be more node based so much as wanting to be able to use a given NPM module.
Sure, but the sort of features I was referring to are more to do with things where one JS engine introduces a new pre-standardization language feature, like async/await. This used to happen a lot, before the standards got ahead of the implementation with E6.
Unlike with browser-embedded JS engines, where "what native APIs are accessible from JS" is a relevant question†, in backend JS runtimes the answer to that question is always "all of them, because they're all just C FFI libraries, and these runtimes use the same C ABI, allowing interoperation with any such library." So for backend runtimes, it's only things to do with the JS engine itself — like language features — where the differences really matter.
Sad such a reasonable question is downvoted, lol. I agree with the sentiment. It's expected any development would want to have the highest reach, which means Node. If Deno supports node features, and node does not support deno clearly the logical conclusion is that features will be node-first, with deno expected to support it anyway. Thus leading to the question of why even bother with Deno?
Deno does have some benefits, such as security model and speed, but those are not things that couldn't be added to Node. Once Node adds the security model why use Deno?
> Thus leading to the question of why even bother with Deno?
1. Native support for TypeScript.
2. Better built-in APIs.
3. Security model.
4. Easy package management.
Node.js is closing the gap. E.g. top-level await, fetch() API, Permissions.
I believe Node.js will follow Deno and implement more and more features. Sort of a npm/yarn situation.
It's cool to see what Deno does, but I don't think you will be left out by sticking with Node.js.
Also Node.js SEA - Single Executable Applications is a Deno-like ("deno compile") feature.
> Easy package management.
If anything, deno's package management is definitely not easy.
And no, "just throw your deps into deps.ts and re-export each manually" isn't easy either.
Nodejs is the de facto platform and ecosystem to write JS backend, and it seemed to me a bit weird that one would want to compete with it without being compatible with it which meant throwing away the very large ecosystem and existing code bases with no good reasons if you wanted to migrate. So congrats to them to have made it now, Deno can still compete on speed or tooling for example. Good Deno ideas will indeed probably make their way to Nodejs (or already did), and it's great, it makes Deno already useful for everyone even if it ends up not being used that much.
About the security model: can someone explain why it's a good idea to have isolation at the interpreter level rather than relying on OS features? (or VMs). I cannot see why a security team would want an isolation system that's different for a specific platform.
> can someone explain why it's a good idea to have isolation at the interpreter level rather than relying on OS features? (or VMs).
Those technologies are platform-specific and difficult to use.
For example, provide the command line for running a Node.js program in Linux without file system access.
In deno, it's
Or, to enable fs access:
deno run main.ts
deno run --allow-read --allow-write main.ts
That said, I agree that I'd rather rely on containers, VMs, etc.
Reinvent of unevil / pledge
Something along the lines of
> docker run -it --rm -v "$PWD":/app -w /app node:18 node main.js
It's a tad longer but it's more flexible too ;)
Of course, now you have to boot and run an entire VM on your MacBook, just to run that one Node.js program.
Ah yes, I always forgot some people don't use Linux as their OS to develop. That always seems weird to me because then they have to launch VMs each time they want to simulate their target OS :D
But I do see your point :)
As if docker doesn't run a VM on Linux when you invoke that one liner.
Official docker image for node is built from Alpine or Debian 
Forgive me if I don't believe that running a full OS on a host OS to run a single node command doesn't amount to running a VM.
It doesn't run a full OS. Merely the nodejs binary with all it's dependencies.
You can think of Docker containers as a way to package an application dependencies, ending at the (Linux) kernel API/ABI.
As in: "a completely different node js binary in its own environment, its own networking, its own file system overlay etc."
I cannot say if your are wrong because of ignorance or bad faith, but in case it's the former: running in a container is not the same as running in a VM, no rewording of the definition of either will make it the same or even equivalent. The difference have some impact on performance and security among other things, I recommend that you take the time to understand the difference if it's a topic of interest for you.
Being a developer!== Linux.
Interesting theory ;)
Easily proven by happy consumers on Apple, Microsoft, Sony and Nintendo devices.
Or the millions of daily passengers in transport mechanisms powered by high integrity operating systems.
I'm kidding of course. But in the specific context of this thread which was Nodejs backend development, I'd still maintain that not using Linux to develop is suboptimal.
Depends if one is stuck in the glory days of UNIX, or has already learnt to embrace native cloud development.
In a way, the glory days of Unix, with users using shared infrastructure is closer to cloud than using Linux locally, which gives you freedom, independence and privacy.
Not when the cloud is running servless and language runtime containers on top of type 1 hypervisors.
All of the major serverless runtimes are running on top of Linux by default.
And almost all systems on AWS are running on Linux/KVM. Even quite a few that report as Xen are actually running on KVM; Amazon added a bunch of code to KVM to lie on guest hypervisor cpuid leaves as well as emulate Xens hypercall interface.
No they aren't, if the cloud in question is Azure, as Hyper V doesn't need a kernel to make it work. The controlling OS is a guest as well, with additional privilege.
Which happens to be a special Windows build, Azure Host OS.
Additionally, bare bones Linux kernel infrastructure for Xen and KVM support isn't UNIX.
"Transcending POSIX: The End of an Era?"
You know that serverless is orthogonal to unikernels, right? Serverless just means dynamically provisioning an instance in response to the load balancer seeing a request. There are no serverless runtimes I know of that don't run as relatively regular processes on a host kernel.
> Additionally, bare bones Linux kernel infrastructure for Xen and KVM support isn't UNIX.
> "Transcending POSIX: The End of an Era?"
Xen and KVM aren't equivalent here.
KVM is ultimately an interface involving file descriptors, mmap(2), read(2), write(2), etc. IMO while not being UNIX™ it still very much embodies the UNIX spirit.
If you're using Docker Desktop, and have it run at startup, that VM is already running when you launch your docker command. It's not like you have to start a new/fresh VM every time you do docker run.
Not on Windows. We have native containers.
> and thus Deno specific stuff will not be developed?
Deno supports typescript out of the box. This alone greatly simplifies any deployment, and even if Deno did not offered anything else it would already take the lead in developer experience.
This is my take as well. Given the relative pain to configure ts projects in node. Especially with the harder lines between esm and cjs modules. It's kind of painful at times in the node space.
Well there’s more than just Node and Deno too. Cloudflare workers, etc. If you want portability across different worker runtimes and not just Deno, you’ll still want to avoid heavy Node API usage.
Yay npm packages
Nah, Deno is just another runtime. Now we have the browser runtimes and multiple server runtimes. Not to mention we also have server runtimes like Cloudflare Workers that are "almost" Node in the sense that they run on V8, but without access to filesystem APIs.
People will make sure to distribute their library so that it works on all of them. They might even use `deno compile` to bundle the library into a single file that can be consumed from any of the runtimes.
Note that even cloudflare workers is adding more node compatibility.
I think this works for the same reason Typescript works. You can adopt with no changes, then slowly take advantage of advanced features.
Deno being Node compatible is the "Embrace" in "Embrace, Extend, Extinguish".
Microsoft’s original successful application of this 3E strategy was predicated on them being the 300 kg gorilla in the market. Deno doesn’t seem to have that. When you’re the underdog, people don’t end up using your extensions without thinking.
I could also work if Deno had to offer more than what Node does, while being compatible. People would start using Deno and then start using Deno specific things which are not compatible with Node.
Long shot though.
I expect deno to convert all of their features to node modules and simply be an opinionated stack, similar to create-react-app vs. next.js. The path they're entertaining now isn't really tenable.
There are many people that feel having Node support harms Deno's goals, but I don't agree.
To me, this is like complaining that you can mix JS into TypeScript projects. The only reason the latter is successful is because you can migrate from the former in a first-class way.
I don't think Deno has the community support to make it on its own steam - that said, I think it's a huge value add in terms of DX. I support them on this 100%.
Node is trying to add in some capabilities of Deno. We'll see which one comes out ahead.
I wouldn't say it necessarily harms Demo's goals, but I think it sort of "harms" the JS community by keeping Node cruft around as a crutch. It's one thing to support Node features when there's no other choice for a package, but then keeping around these Node APIs just encourages developers to keep using them no matter what runtime you are using. By the time that nearly packages support Demo in one way or another, I expect most new packages to still predominantly be written in Node style.
Just my opinion, but I'd rather that not be the case.
deno does not have any inherent advantages over node if they continue to support node functionality. I won't be surprised if package.json support is next. literally the purpose and sole advantage of deno was that they did not have node cruft. things like speed are not inherent advantages. it's true deno is written in rust, but node is basically v8, which has its own advantages.
> deno does not have any inherent advantages over node if they support node
Could you be more specific about how this harms deno? It is just "cruft"?
for one the security model is incompatible with node APIs. as a result even with this post, deno doesn't support all npm packages. however if deno were to support all npm packages, it would necessarily basically have to implement the entire node api, including support for pre async/await (aka callbacks). this is but a single example. deno was able to ignore all of that because compatibility was not an original design decision
I think, in general the requests are largely to support specific, and generally popular npm modules. People wrigin software running under Deno aren't generally asking for "all" of node's API, but enough to where at least the most popular modules out of npm actually work. I think we're largely at that point now.
Haven't tested it, but one of the modules I had a lot of trouble importing when MS-SQL was a major database I interacted with was `mssql` backed by `tedious`. I'm at least able to `import mssql from 'npm:mssql';" now. I don't have many other good/complex imports that weren't working before or were lacking suitable deno alternatives. Back when trying to use the likes of esm.sh and similar, it used to blow up spectacularly.
> for one the security model is incompatible with node APIs
No it isn't.
> deno was able to ignore all of that
So maintaining a Node.js stdlib (or subset thereof) is more work for the Deno team. I agree, but that seems a weak argument for harming a Deno user.
> No it isn't.
sure it is. how could deno maintain its security model and implement all of the node apis? part of why it works is because there's a standard lib and there's no way to obscure usage and thus circumvent the permissions. unless your answer is that --allow-run is the solution. even with the OP post, they don't even support child_process with deno deploy, which is why, but clearly they can't support everything and still maintain security, which is the point.
consider just the c++ embedder apis. how exactly would deno deal with that with respect to permissions?
Bartek from the Deno team here, let me clarify a few things.
> for one the security model is incompatible with node APIs.
All Node.js APIs are polyfilled using Deno APIs and as such these Node.js API are subject to the same permission model as regular Deno programs.
> however if deno were to support all npm packages, it would necessarily basically have to implement the entire node api, including support for pre async/await (aka callbacks)
We're not aiming for 100% compatibility, though we managed to polyfill a hefty amount of built-in Node modules, including ones that are callback based.
> consider just the c++ embedder apis. how exactly would deno deal with that with respect to permissions?
This is the same situation as with Deno's FFI API. You need to pass `--allow-ffi` flag to enable usage of `Deno.dlopen` (or `require("./foo.node")` for N-API extensions). That said when you load dynamic libraries all bets are off - we can't control what the dynamic library can do and you effectively open up your whole system. Still, you can't load such libraries unless `--allow-ffi` flag is passed.
Hope this clears up some things.
> We're not aiming for 100% compatibility, though we managed to polyfill a hefty amount of built-in Node modules, including ones that are callback based.
yeah, I'm aware of this. my point was that you couldn't 100% compatibility without compromising. fwiw it's a good thing. node can be a security nightmare if your team is not disciplined about dependencies.
w.r.t to node apis, technically you are like you say polyfilling them. and with that implementation differences hopefully allow you to continue to polyfill.
Deno is moving into a similar space as Kotlin started at by adding all this interop—they're trying to be the "better Node". Meanwhile Kotlin is frantically trying to differentiate itself because Java is closing the gap, but it's hard for them to do because they've spent so long piggybacking on the Java ecosystem.
Deno is very vulnerable to the same fate. Yes, it's easier to get adoption if you can plug into an ecosystem that is already popular, but then it's not your ecosystem and the behemoth that actually owns the ecosystem will feel the threat and adapt.
If you don't prioritize interop, your initial adoption will be much much slower, but if you make it out of the early stages you have an ecosystem of your own that has its own distinct advantages. The incumbent can't just pull in a few good features and thereby take your mind share.
Deno Deploy is the killer feature for me, and it’s ultimately the main product of Deno, Inc. too. Node support just makes it easier to get existing software running there.
I don’t think it will suffer the same fate as Kotlin because a lot of the value add is in Deploy, Deno KV, etc.
What do you mean by "same fate as kotlin"? I would say Kotlin is doing great. Anything I missed?
You missed the parent comment this is in reply to
Yeah i guess i kind of did., I should have asked the parent comment. I'm not a java/kotlin developer but for me it looks like kotlin is thriving. Is that not how it looks for insider's?
Parent here, and I'm writing as someone who loves Kotlin and much prefers it to Java.
Kotlin is doing fine, but its growth has slowed a lot and the team is pivoting rapidly to multiplatform to try forge a niche that isn't just "better Java". That pivot isn't smooth because most Kotlin code—even the standard library—depends heavily on the JVM and Java libraries.
I didn't mean "fate" to imply that Kotlin as a language is dying, just that their position as "better Java" is no longer tenable and they've had to shift strategy dramatically to try to stay relevant. That's what I'm afraid will happen to Deno as Node catches up.
Have you used Cloudflare Workers? How does Deno Deploy stack up, if so?
Have you use vercel before?
Personally, I haven't heard of any Kotlin devs going back to Java nor of any Deno devs going back to Node.
I have inherited Deno web app in my job and I cannot wait to migrate it to Node
Genuinely curious the motivation here
I'm not the OP, but I've built a little bit of software  in Deno. I don't know if I'd do it again. Thoughts, in no particular order:
- Big plus: the built-in stdlib is strong (coming from Node; it's not as strong as Python or even Ruby, but I'll take what I can get). The stdlib is also pretty "good Unix citizen" focused--it's very easy to build an ergonomic command-line application.
- Theoretical plus: the capabilities-based security model is smart and cool.
- In-reality minus: you end up passing most `--allow` flags anyway for anything that isn't trivial. It could scope down to specific modules if you are a tryhard, but I am not sufficiently a tryhard, and this really should just be within the capability of Deno to figure out and recommend for you.
- Moderate plus: `deno compile` being built in is nice, and it is easier than the Node `pkg` library from Vercel.
- Small minus: The set of targets for `deno compile` is limited, though, and (for reasons that are both reasonable and unfortunate) it spits out truckasaurus-sized executables, which is a bummer.
- Enormous, world-stopping minus: dependency management. It's bad, and it's not easy to get around. "Just put all your deps in a TypeScript file and export it" is not the amazing solution that its adherents want you to think it is. The developer experience of upgrades is annoying and unpleasant and `deno-upgrade` helps but makes your project feel out-of-control. (Import maps don't really help, it's just another road into the same unpleasantness and since they don't work if you're writing a library I don't think you should ever use them at all; just stay consistent between applications or libraries.)
- Whiny minus: VScode support is pretty bad. It exists, but it's not great, and there's a weird lag to dependency management that I never figured out.
- Real minus: the Deno VScode stuff freaks out when you use a Node project, even if you set `deno.enabled: false` in your .vscode/settings.json file.
There are definite, real benefits to some of what Deno does. But I just don't see why I'd continue to use it over Just Continuing To Use Node.
 - https://github.com/eropple/tmuxed
The way I see it, if Deno only ever existed to push node to do better that in itself is a universal win for everyone.
This may be bad for Deno if Node will close the gap and okay if it doesn't, but both cases are good for users.
Hey folks - I worked on this. AMA
Hi, thanks for this. Question: Do all Node APIs work as-is? For instance, I opened an issue for Deno stdlib's Conn interface to expose more state (like the ones available in Node: ready, half-open, writable, pause, resume, closed etc) for sockets, but those are unimplemented: https://github.com/denoland/deno/issues/13636
Most Node APIs work just like they do in Node, yes. Some are not yet implemented (like the ones you mentioned). We'll be addressing them in priority order based on user feedback and how many NPM packages are blocked by the given feature.
no question; just wanted to say thank you for your time & effort :)
I listened to the SE Radio episode on Deno you did that covered compatibility. Just wanted to say it was a solid episode and gave me a lot of food for thought.
Slowly Deno is just becoming Node written in Rust with some added flexibility in certain areas. Not necessarily a bad thing but it feels like its three years too late to get major traction. Native TS is neat, but we also have TS compilers that are measured in milliseconds now.
I don't think the speed matters persa, what annoys me is when starting a node project I have to install typescript, jest, eslint (any plugins) then whatever dependences I am using and then set up a tsconfig and what every else also needs a config file.
In deno you can just open your ide, add some imports to the import map and you're ready to code.
Note that import maps are optional. I mostly just open my editor for a Deno project and I'm good to go. :)
This is it for me too... with Deno, I can write a fully contained one-off script with a shebang and use it for general shell scripting.. with node, it was never that simple. Though having to use the `#!/usr/bin/env -S -- deno run ...` is still a little more awkward.
Direct imports that the runtime caches for you, vs node_modules is way easier to deal with most of the time.
Am I the only one reading this right or am I the only one reading it wrong.
Deno is not supporting node.js built-ins. It's deno deploy. Meaning that this will not work on other hosting platforms, right... or?
Deno has already been seeing increasing support for Node's API and built-ins... this means, they are now also available for running in Deno Deploy (cloud environment)... if you were using something where you deployed your own Deno (docker, etc) then you could already to this.
Note: Cloudflare Workers is also starting to support a lot of Node APIs as well (opt-in), so bundles will likely be able to run in both of them and others. Can't speak specifically to it, but Bun will probably also largely work.
Thanks. That explains it. See that it was added to deno in jan. I guess the last version on deno made it ready to be used on deno deploy.
I recently got a simple edge function working on Netlify for a tiny hobbyist project, with some minor confusion but it was fine. I'm wondering how Deno Deploy compares?
Have not tried Netlify so can't exactly compare. But Deno Deploy is a very convenient FaaS. No discernible cold starts. Fast automatic deployment on push. No build step hassle.
I'm really excited for when they also get state (Deno kv).
At this point, given the state of module loading on node and other ecosystem problems, my reasons for switching to deno (or bun) are dwindling.
Uhh do you not realize deno has an entirely different import system where you import by direct resource URL, or one level of indirection through an import map (just like the web)? There's no complex node_modules resolution, no .mjs extension nonsense, no package.json bits to flip. Imports are radically simpler in deno.
That's my point. They fixed and defined the ecosystem which is great. I feel like everyone is forgetting what a mess Node is right now.
Just to clarify - we do have support for node_modules/ resolution (with all of its quirks and gotchas), otherwise we wouldn't be able to load npm packages. However we made a hard stance that CommonJS is only supported in npm dependencies and cannot be used in user code (ie. you must use ESM in your application code).
Until you try to build a TS project that imports an .mjs from node_modules that doesn't work right. Oh, set the project to type=module, nope, then other crap breaks. I mean, you can get it all working, but simple and easy are two words I would not use for modern node, especially when working with typescript.
Pst, you can do the same thing in Node.js. Nothing is stopping you.
Could you please explain what Deno is like I am five? (three actually)
Ryan Dahl created Node.js, had regrets, and started from scratch with Deno to address those issues 
Mostly like node but made by someone else and not actually node.
Well, technically it’s made by the same initial author.
Except it's made by the same person
same author, arguably same purpose, but this time with rust and typescript.
ironically, the more node js goes into Deno, the less likely I am to switch. imho they should stay the course and not include too much node stuff.
deno has some benefits (fast, included ts, linter, formatter, etc.), but without node compatibility, i will not switch to deno.
I am not saying deno does not have benefits. I am saying you can get many of those things with node already. I see deno more and more as an opinionated set of things + node. This is not a bad thing.
but if you already have a huge legacy node project why would you switch to deno? or are we all going to pretend to forget why Deno was even created?
Yep. I saw Deno as intended to be a platform for new projects that want to start fresh without all the legacy cruft from Node. Somewhere along the way they decided it was a priority to be able to transition legacy Node projects to Deno, and I'm afraid that what's going to happen is it will freeze the ecosystem's development of independent solutions in favor of just using Node libraries for everything.
I don't think this will happen. People _love_ cutting edge innovation. Cutting edge innovation happens on cutting edge platforms, not in the legacy.
>People _love_ cutting edge innovation.
Only the people who like having to rewrite everything with every breaking change that happens on cutting edge platforms. It's not all that fun for most people. I'll wait until "new shiny" isn't as new and shiny, when it finally becomes stable and dependable. Until then the current stable platform is what I'll continue building on because it still does everything I need it to do.
I disagree. people love a robust ecosystem, not innovation for innovation's sake.
I think you are both right. Some people love innovation, others love stability.
Yes, everybody loves innovation, until they realize, that stability saves much lifetime.
The interesting part of Deno for me is mainly the benefits of the runtime & the idea of using v8 isolates as an alternative to containers etc.
I do wonder about the long-term effects of Deno being Node-compatible; will it result in only Node programming being done since "Deno will handle it fine" and thus Deno specific stuff will not be developed?