Deno 2: Building REST APIs Without ‘node_modules’, Maximum Security, and Node.js Compatibility

Development tutorial - IT technology blog
Development tutorial - IT technology blog

The ‘node_modules’ Nightmare and Configuration Chaos

Imagine this: You only need to write a simple API, but your node_modules folder already consumes 400MB of disk space. I once refactored a 50,000-line project. Upgrading dependencies and fixing conflicts in tsconfig.json alone took three full workdays. Not to mention installing eslint, prettier, or jest with dozens of cumbersome config files.

Node.js is powerful but carries a heavy burden of legacy debt. Regarding security, Node.js allows every package to access the hard drive or environment variables by default without asking. In an era of rising supply chain attacks, this is a concerning vulnerability.

What Does Deno 2 Solve That Node.js Misses?

Ryan Dahl—the creator of both Node.js and Deno—designed Deno 2 to fix past mistakes. The biggest highlight is the “all-in-one” experience. You don’t need to install tsc to run TypeScript, nor do you need prettier to format code. Everything is built-in.

Notably, Deno 2 is now highly compatible with the npm ecosystem. You can drop express or mongoose into your project without any hurdles. Startup speeds are also significantly faster thanks to the removal of complex module resolution checks used in Node.js.

Ultra-fast Deno 2 Installation

Forget complex installation steps. On Linux or macOS, you only need to run a single command:

curl -fsSL https://deno.land/x/install/install.sh | sh

Type deno --version to check. If you see version 2.x, you’re ready to experience the most modern runtime available today.

Building a REST API: No Config, No node_modules

Let’s create a server.ts file. We’ll use pure TypeScript without any configuration files.

// server.ts
const kv = await Deno.openKv(); // Built-in key-value database

interface User {
  id: string;
  name: string;
}

Deno.serve(async (req) => {
  const url = new URL(req.url);
  const path = url.pathname;

  // Get User list
  if (path === "/users" && req.method === "GET") {
    const users = [];
    for await (const res of kv.list({ prefix: ["users"] })) {
      users.push(res.value);
    }
    return Response.json(users);
  }

  // Add new User
  if (path === "/users" && req.method === "POST") {
    const body = await req.json();
    const id = crypto.randomUUID();
    const newUser = { id, ...body };
    await kv.set(["users", id], newUser);
    return Response.json(newUser, { status: 201 });
  }

  return new Response("Not Found", { status: 404 });
});

The difference is that you don’t need to run npm install. Deno automatically manages and caches modules intelligently, keeping your project directory clean.

Sandboxing Security: Power in Your Hands

This is my favorite feature. If you run deno run server.ts, Deno will immediately block it because you haven’t granted network access. To make the API work, you must explicitly specify permissions:

deno run --allow-net --allow-read --allow-write server.ts

This “explicit permissions” approach is extremely secure. If a third-party library contains malicious code trying to steal data, Deno will lock down that behavior unless you specifically allow it.

Using npm Libraries in Deno 2

Deno 2 removes the library shortage barrier using the npm: prefix. If you still want to use Express for familiarity, look at the example below:

import express from "npm:express@5";
const app = express();

app.get("/", (req, res) => {
  res.send("Express is running smoothly on Deno 2!");
});

app.listen(3000);

The system automatically downloads Express to a global cache. No messy package.json, and no wasted disk space for every individual project.

Real-world Experience: When Should You Switch to Deno 2?

If you’re building new microservices or writing CLI tools, Deno 2 is a top-tier choice. Eliminating config files doubles prototyping speed. However, for legacy projects heavily dependent on Node.js native C++ libraries, you should carefully check compatibility before migrating.

The biggest lesson I’ve learned: The best technology is the one that lets you focus on logic instead of infrastructure. Deno 2 is proof of that. It reduced build times from 3 minutes to 30 seconds in several of my real-world projects.

Optimizing Workflows with Deno Task

Instead of using scripts in package.json, Deno uses a cleaner deno.json file:

{
  "tasks": {
    "dev": "deno run --allow-net --watch server.ts",
    "start": "deno run --allow-net server.ts"
  }
}

Just type deno task dev, and the server will automatically reload whenever you change the code. Extremely convenient!

Conclusion: Start with Small Scripts

Don’t rush to migrate entire massive systems to Deno immediately. Experiment with automation scripts or small auxiliary services. You’ll feel a sense of relief escaping the node_modules mess. With version 2, the barrier to entry is almost zero. Give it a try today!

Share: