Skip to content
PRSINDIA

Node 22 LTS · NestJS · Fastify

Node.js Development

Node is the right answer for real-time tiers, streaming and high-concurrency I/O — and the wrong answer for CPU-bound work. We build TypeScript services that know the difference, and we will tell you which one you have.

  • 10k+ concurrent sockets per node
  • Event-loop lag alarmed in production
  • Strict TypeScript, no escape hatches
  • BullMQ jobs with dead-letter replay
Why Node

Brilliant at connections. Bad at arithmetic.

Node.js does one thing extraordinarily well: it holds an enormous number of connections open while doing almost nothing on each of them. That is precisely the shape of a live-tracking feed, a chat tier, a presence service or a dashboard that pushes instead of polling — and it is why we reach for Node on those, and only those. The same single-threaded event loop that makes it excellent at I/O makes it fragile under computation. One blocking call and every open connection waits. We design around that with hard boundaries, worker threads and queues, and we alarm on event-loop lag in production. If your system is really an order pipeline with a database at the end of it, we will tell you that Laravel is the better answer and explain why.

Talk to a backend engineer
0k
Sockets per node

Concurrent WebSocket connections on a single process, in production, on modest hardware.

0ms
p95 API latency

Fastify with schema-based serialisation, in front of PostgreSQL with a connection pool that is actually sized.

<20
Event-loop lag

Our production alarm threshold. Past it, someone is paged — before a customer notices anything.

0%
Strict TypeScript

No implicit any, no escape hatches merged to make a deadline. Zod validates every external boundary.

How we actually build it

Node is the right tool for a narrow, important set of problems: systems that hold a great many connections open, systems that pass data around more than they compute on it, and systems whose team already writes TypeScript everywhere else. Outside that, we will usually point you at Laravel or Go and be honest about why.

The event loop is the whole design, and it is also the whole risk

Node handles ten thousand idle WebSocket connections on a single process without breathing hard, because an idle connection costs almost nothing. That is genuinely excellent, and it is why we reach for Node on real-time tiers: live tracking, chat, presence, collaborative editing, dashboards that push rather than poll.

The same property is the failure mode. One synchronous JSON parse of a 40 MB payload, one tight loop over a large array, one badly-written regex meeting a hostile input, and the event loop stops — and every one of those ten thousand connections is now waiting on it. We treat CPU-bound work as a hard architectural boundary: it goes to a worker thread, a BullMQ job, or a different service entirely. We instrument event-loop lag as a first-class production metric and alarm on it, because by the time users notice, you are already several minutes into an incident.

NestJS when the system will outlive its first team

Express is fine for a service that fits in one engineer's head. For anything a team will maintain for years, we use NestJS: modules, dependency injection, decorators, class-validator at the boundary, and a structure that means the twelfth developer puts their code where the first one would have. It is deliberately Laravel-shaped, and that is the point — most Node codebases that go bad go bad from an absence of enforced structure, not from a shortage of clever ideas.

Where raw throughput is the requirement and the surface is small, we use Fastify instead. It is meaningfully faster than Express, has schema-based validation and serialisation built in, and does not pretend to be a framework for a large team.

Types all the way to the database

TypeScript in strict mode, no exceptions and no any smuggled in to make a deadline. Drizzle or Prisma for the data layer so the schema is typed at the query site, Zod at every external boundary because a type is a compile-time promise and the network does not care about your promises. Where the client is also TypeScript, tRPC removes the entire hand-written API contract and the class of bug where the frontend and backend disagree about a field name.

Running it

Stateless containers behind a load balancer, one process per container, orchestrated rather than clustered by hand. Redis for shared state and pub/sub between instances, because the moment there is more than one Node process, in-memory state is a bug waiting for its moment. BullMQ for background jobs with retries, backoff and a dead-letter queue. Graceful shutdown that drains in-flight requests on SIGTERM. OpenTelemetry traces, and event-loop lag on the same dashboard as p95 latency.

The honest part

When Node is the right call — and when it is not.

  Choose Node.js Choose something else
Real-time: chat, tracking, presence Yes. This is what the event loop was built for, and it holds tens of thousands of idle connections without complaint. Go, if you need a hundred thousand connections per box and have the team to operate it.
Order, payment and inventory logic Only if your team is TypeScript end to end and that operational simplicity is worth more than the framework gap. Laravel. The workload is database-bound, so Node buys you no speed, and you get Horizon and a Filament admin for free.
Image, video or report processing Never in the request path. It must go to a worker thread or a queue, or it takes the whole service down with it. A dedicated worker service — Go, Python or a managed pipeline. Keep the CPU-bound work out of your socket tier entirely.
Machine learning or data science No. The libraries are not there and you will reimplement, badly, what already exists elsewhere. Python, as a separate service. Have Node call it over a queue. This is boring and it works.
Sharing types with a React front end Strong. tRPC or shared Zod schemas delete the entire class of bug where client and server disagree about a field. Nothing matches it here. This is the most underrated reason to pick Node and the one teams mention least.
Small team, complex admin needs You will build the admin panel by hand, and it will take longer than you think. Budget for it honestly. Laravel with Filament. A full back office over your models in days. This is not a close contest.
What we build

Node.js work we take on.

Real-time tiers

Live order and vehicle tracking, presence, chat, collaborative editing. Socket.IO or raw WebSockets with Redis pub/sub across instances.

API gateways and BFFs

A backend-for-frontend that aggregates a mess of internal services into one sane, typed contract the client can actually consume.

Event-driven services

Kafka or Redis Streams consumers, BullMQ workers, idempotent handlers, dead-letter queues with a replay path an operator can use.

tRPC monorepos

End-to-end type safety from the database schema to the React component, with no hand-written API contract to drift out of date.

Streaming and ingestion

High-volume ingestion pipelines where data is moved and transformed rather than computed on, and backpressure is designed rather than hoped for.

Node rescue

An Express codebase that grew past its structure. Restructured into NestJS modules, typed strictly, and instrumented so you can see it.

Characteristics

What you get, and what you must design around.

  • Concurrency is nearly free

    An idle connection costs a file descriptor and a little memory. Twelve thousand of them on one process is unremarkable.

  • Event-loop lag is the metric

    We alarm above 20ms. It is the earliest signal that something is blocking, and it fires long before p95 latency notices.

  • CPU work leaves the request path

    Worker threads or BullMQ jobs. This is a hard architectural boundary in our Node codebases, enforced in review.

  • Types reach the database

    Strict TypeScript with Drizzle or Prisma, Zod at every external boundary. A type is a promise; the network has not read it.

  • Stateless containers, Redis for shared state

    The moment there is a second Node process, in-memory state is a bug waiting for its moment. We do not keep any.

  • Graceful shutdown, drained

    SIGTERM drains in-flight requests and closes sockets cleanly. A deploy should not be a small outage you have learned to ignore.

The stack

What ships with a Node build from us.

Node.js 22 LTS
TypeScript
NestJS
Fastify
tRPC

Not sure Node is the right answer? Good.

Tell us what the system actually does and we will tell you honestly whether Node is the tool for it — including the times the answer is Laravel, Go or Python. That conversation is free and it takes twenty minutes.

FAQ

The questions you were going to ask on the call.

Laravel, for most business systems — orders, payments, inventory, workflow, reporting, admin. It gets you there sooner and the codebase stays legible. Node, when the system is genuinely real-time or streaming: live tracking, chat, presence, collaborative editing, or tens of thousands of open connections. Also Node when your team is TypeScript end to end and the operational cost of a second language is real. Anyone who answers this question without asking what the system does is guessing.

It is extremely fast at I/O and quite bad at computation, and conflating the two is where teams get hurt. Ten thousand idle WebSocket connections on one process is comfortable, because idle connections cost almost nothing. One synchronous parse of a large payload blocks all ten thousand of them, because there is a single event loop and you just stopped it. Node is fast at exactly the thing it was designed for, and you must architect CPU-bound work out of the request path.

NestJS for anything a team will maintain for years. It gives you modules, dependency injection and enforced structure, which is what stops the twelfth developer inventing a thirteenth way to organise a controller. Express for a small service that fits in one engineer's head. Fastify when raw throughput matters and the API surface is small — it is faster than Express and has schema validation and serialisation built in.

We treat CPU-bound work as a hard architectural boundary. Image processing, report generation, large parses, cryptographic work and anything with an unbounded loop go to a worker thread, a BullMQ job or a separate service — never inline in a request handler. Then we instrument event-loop lag as a production metric with an alarm on it, so a regression surfaces on a dashboard rather than as a customer complaint. Most Node outages we are called in to review are one blocking call that nobody was measuring.

It can, and we have built exactly that. But be honest about why you are choosing it. If the reason is "our team writes TypeScript", that is a legitimate reason and we will build it well in NestJS with Drizzle and strict types. If the reason is "Node is faster", that is not true for this workload — an order pipeline is database-bound, and Laravel would get you there sooner with a better admin panel for free. We would rather have that argument before the build than during it.

A real-time service or API tier is typically 8 to 14 weeks from around ₹8,00,000. A full platform with a real-time layer, background processing, integrations and an admin surface is 16 to 26 weeks and starts around ₹20,00,000. If you already have a backend and need a real-time tier bolted onto it cleanly, that is often a 4 to 6 week piece of work and we are happy to scope it that way.

Proof

Shipped, measured, still running.

All case studies

NM Company

A portfolio and enquiry site for events firm NM Company

A visual portfolio and enquiry website for an event management and supplies firm — presenting a full...

Read it

Swasthya Sarathi

A healthcare-companion platform for Swasthya Sarathi

A multi-service healthcare platform that helps people find hospitals, doctors, labs, medical stores,...

Read it

MV Tech Education

A course and admissions platform for MV Tech Education

A course-catalogue and admissions website for a Bihar vocational institute — leading with industrial...

Read it

Let's talk node.js development

Bring us the hard version of the problem.

A senior engineer reads every enquiry. You'll get a real answer — scope, risk and a number — within one business day.