Developed By Ken Key

Node.js Development for New York Businesses: What Actually Works in 2026

By Ken Key Jun 24, 2025 5 min read Updated Oct 16, 2026

Node.js Development for New York Businesses: What Actually Works in 2026
The short answer

For most New York businesses, Node.js works best as the API and integration layer: I/O-heavy services, real-time features, and webhooks. It is a poor fit for heavy CPU work like video encoding or big data crunching. Keep it boring: ESM, built-in test runner, and a compiled production build.

Part of the complete web development guide.

On this page

Node.js turned fifteen this year, and it has quietly become the default backend for a huge chunk of the web. That means the interesting question is no longer “should I use Node?” It’s “which parts of my stack should be Node, and how do I keep it fast and boring in production?” Here’s my honest read after building and maintaining Node services for clients around New York and beyond.

What actually changed by 2026

If you last looked at Node around 2018, a few things are different now.

  • ES modules are the norm. The CommonJS versus ESM argument is mostly settled. New projects ship ESM, and the interop pain has shrunk to a manageable edge case.
  • The built-in test runner is real. node:test and node:assert handle most projects without Jest or Mocha. Fewer dependencies, faster CI, one less thing to upgrade.
  • Native TypeScript execution. Node can strip types and run .ts files directly for development. You still compile for production, but the day-to-day loop got much shorter.
  • Fetch, WebSocket, and structuredClone are built in. The list of “install a package for this” keeps shrinking.
  • Permission model. You can restrict filesystem, child process, and network access at startup with --permission. It’s not a sandbox replacement, but it’s a cheap extra layer.

None of this is hype. It’s the accumulated result of the project finally absorbing the good ideas from the ecosystem instead of fighting them.

When Node is the right call (and when it isn’t)

Node is excellent at I/O-bound work: APIs, real-time features, streaming, anything where you’re waiting on a database or another service. It’s a poor fit for heavy CPU work like video encoding, large image processing, or dense numerical computation. You can do those things, but you’ll be fighting the runtime the whole time.

A quick decision guide:

  • REST or GraphQL API, moderate traffic: Node is a great default. Huge hiring pool, mature tooling.
  • WebSockets, chat, live dashboards: Node shines here. The event loop was built for this.
  • Server-rendered marketing sites: Fine, but a static build or a lighter runtime is often cheaper to host and simpler to secure.
  • CPU-heavy background jobs: Use a worker thread, or hand the job to a service written in Go, Rust, or Python. Don’t pretend the event loop can absorb it.
  • Data science and ML training: Wrong tool. Use Python. Call your Node API from it if you need to.

A small, current example

Here’s a minimal HTTP server using only what ships with Node today. No Express, no dotenv, no body parser. This is genuinely all you need for a lot of internal services.

// server.mjs
import { createServer } from 'node:http';

const port = process.env.PORT ?? 3000;

const server = createServer(async (req, res) => {
 if (req.method === 'GET' && req.url === '/health') {
 res.writeHead(200, { 'content-type': 'application/json' });
 res.end(JSON.stringify({ ok: true }));
 return;
 }

 if (req.method === 'POST' && req.url === '/echo') {
 const chunks = [];
 for await (const chunk of req) chunks.push(chunk);
 const body = Buffer.concat(chunks).toString('utf8');

 res.writeHead(200, { 'content-type': 'application/json' });
 res.end(JSON.stringify({ received: body.length }));
 return;
 }

 res.writeHead(404).end();
});

server.listen(port, () => {
 console.log(`listening on ${port}`);
});

And a test for it, using the built-in runner:

// server.test.mjs
import { test } from 'node:test';
import assert from 'node:assert/strict';

test('health endpoint responds ok', async () => {
 const res = await fetch('http://localhost:3000/health');
 assert.equal(res.status, 200);
 const body = await res.json();
 assert.equal(body.ok, true);
});

Run it with node --test. That’s it. No config file, no transformer, no plugin chain. For teams that have been dragging a 400-package dev dependency tree around for years, this is a genuine relief.

Production realities nobody mentions in tutorials

The tutorial version of Node and the production version are different animals. A few things I’ve learned the hard way:

1. One process per core, not one process total

Node runs your JavaScript on a single thread. If you have a 4-core box, you’re wasting 75% of it with a single process. Run a cluster or, more commonly now, run several containers and let your orchestrator handle it. On a plain VM, the cluster module still works fine.

2. Memory limits are not suggestions

Set --max-old-space-size below your container’s memory limit, not at it. A Node process that hits the container ceiling gets OOM-killed with no stack trace. Give it headroom and let it garbage collect.

3. Graceful shutdown is not optional

When your orchestrator sends SIGTERM, you have a small window to finish in-flight requests before it kills you. Handle it.

process.on('SIGTERM', () => {
 server.close(() => {
 console.log('closed cleanly');
 process.exit(0);
 });

 setTimeout(() => process.exit(1), 10_000).unref();
});

4. Unhandled rejections will take you down

Since Node 15, an unhandled promise rejection crashes the process by default. That’s the right behavior, but it means you need a top-level handler that logs properly before exiting, so you have something to debug.

5. Watch your dependency count

The npm ecosystem is a strength and a liability. Every transitive dependency is code you didn’t write, don’t review, and now own the security of. Run npm audit, but also just look at your tree occasionally and ask whether you need all of it.

Where this fits for a New York business

Most of the work I do for local companies isn’t exotic. It’s a marketing site with a CMS, a booking API, an internal dashboard, an integration between two SaaS tools that don’t talk to each other. Node is a solid fit for the API and integration layers, and it pairs well with a frontend that’s already JavaScript.

What matters more than the runtime choice is whether the thing is maintainable in two years by someone who isn’t you. That’s why I lean toward fewer dependencies, standard library features, and boring architecture over clever architecture. If you’re weighing a rebuild or a new backend and want a straight answer on whether Node is the right fit, that’s the kind of work I do through custom web development for clients on Long Island and in the city.

FAQ

Is Node.js still a good choice for new projects in 2026?

Yes, for I/O-heavy backends like APIs, real-time features, and integrations. It’s a weaker fit for CPU-heavy work, where Go, Rust, or Python will serve you better. The runtime itself is more capable and less dependency-hungry than it was five years ago.

Do I still need Express or Fastify?

Not always. The built-in HTTP server handles a surprising amount on its own, and for small services it’s often enough. For larger apps with routing, middleware, and validation, Fastify is my usual pick. It’s fast, well-maintained, and its plugin model avoids the middleware ordering messes that plague older Express codebases.

How do I keep a Node service from falling over in production?

Run multiple processes, cap memory below the container limit, handle SIGTERM with a graceful shutdown, log unhandled rejections before exiting, and keep your dependency tree small enough that you can actually reason about it. None of that is glamorous, but it’s what separates a service that runs for a year from one that pages you at 2am.

Have a project like this?

I do custom web development for Long Island businesses. If you need this done right, let’s talk.