Node.js
API and worker layer for most of the systems we ship — one language across the stack.
Node.js is our default server runtime for new systems, chiefly because one language across the stack means shared validation, shared domain types and a hiring pool that covers both ends. For the workloads most of our clients run — API serving, integration, orchestration, background jobs — its performance profile is more than adequate and its ecosystem is unmatched.
We use Express for small services where the framework should stay out of the way, and NestJS where an application is large enough that convention and dependency injection earn their overhead. The choice is made on expected size and team, not on preference.
Where Node is the wrong answer we say so. CPU-bound numerical work belongs in Python or a compiled language. Long-running stateful process control does not belong in a request-response runtime. We have moved specific workloads out of Node for exactly these reasons.
Where it fits
What Node.js genuinely gives us
One language, one set of types
Validation schemas and domain models are written once and used by the API, the web front end and the mobile app.
Excellent I/O concurrency
API gateways, integrations and orchestration — workloads dominated by waiting on other systems — are exactly what the runtime is good at.
Ecosystem depth
A well-maintained library exists for nearly every integration an Indian business needs, from GST APIs to payment gateways to Tally.
Operationally simple
Containerises cleanly, starts fast, and scales horizontally without ceremony.
Dependency and supply-chain discipline in Node
The npm ecosystem is Node’s greatest advantage and its most persistent liability. A modest application routinely resolves to several hundred transitive packages, any of which may be abandoned, may change ownership, or may ship a compromised release. This is not theoretical — supply-chain incidents in this ecosystem are regular events, and most Node applications in production have no process for responding to one.
The controls are unexciting and effective. A committed lock file so builds are reproducible and a dependency cannot change under you between deployments. Automated vulnerability scanning wired into CI so a known issue fails the build rather than appearing in a quarterly report. A deliberate policy on adding dependencies, because a package that saves twenty lines is rarely worth the maintenance surface it adds. Periodic pruning of packages that are no longer used, which almost every long-lived codebase accumulates.
We also separate build-time from run-time dependencies properly, so the production image does not ship the entire toolchain, and pin the Node runtime version rather than tracking whatever the base image happens to provide. These measures cost almost nothing to establish at the start and are awkward to retrofit under incident pressure.
Where Node.js services succeed, and where they quietly fail
Node is exceptionally good at what most business systems actually do: accept a request, talk to a database and two or three other services, assemble a response, and do that concurrently for many users. It is a poor choice for sustained CPU-bound work, and a great deal of the Node trouble we are asked to diagnose comes from someone putting image processing, large report generation or heavy parsing on the same event loop that serves user requests. The symptom is a service that is fast until it is suddenly and inexplicably not, and the fix is to move that work to a queue and a separate worker.
The second recurring failure is operational rather than architectural. Node services are easy to start and easy to run badly: no structured logging, so an incident is investigated by reading raw console output; no health or readiness endpoints, so orchestration restarts things at the wrong moment; unhandled promise rejections crashing a process at three in the morning; and connection pools sized by guesswork. None of this is difficult to get right, but it is almost never done by teams shipping their first production service.
We build Node services the boring way: typed throughout, layered so business logic is testable without a running server, instrumented from the first commit, and deployed with the operational endpoints and dashboards that make an incident a ten-minute investigation instead of a two-hour one.
Queues for anything that can be slow
Any operation that depends on a third party — sending a message, calling a payment gateway, pushing to an ERP, generating a document — goes onto a queue rather than running inside the request. The user gets an immediate response, the work happens with retries and backoff, and a failure produces a dead-lettered job with its payload rather than a lost transaction.
This one pattern accounts for a large share of the difference between a system that degrades gracefully under load and one that times out and loses data.
Observability from the first deployment
Structured JSON logging with a request identifier that flows through every downstream call, traces on route handlers and database queries, and error reporting with enough context to reproduce. Health and readiness endpoints that reflect actual dependency state rather than returning 200 unconditionally.
Without these, diagnosing a production issue in a distributed Node system is guesswork. With them it is usually a five-minute query.
How Node.js projects usually go wrong
These are the failure modes we look for first when we are called in to rescue somebody else's implementation.
Node.js questions we get asked
Including where we would recommend something other than Node.js. Call +91 70033 91355 and you will get the same answer from an engineer.
Depends far more on your team than on the technology. If you have PHP developers maintaining a Laravel or CodeIgniter estate, adding a Node service creates a second discipline to hire for and support — we will usually build in PHP and make it excellent. If you are starting fresh or already have JavaScript skills, Node gives you one language across the stack. Both are entirely capable of running serious business systems.
For I/O-bound workloads, comfortably — we run services handling thousands of requests per second on modest infrastructure. Where it is the wrong tool is sustained CPU-bound computation: heavy numerical processing, image transformation at volume, or large data transformations. Those we move to Python, a worker pool, or the data platform, and we identify them during architecture rather than after a load test fails.
Services built on Node.js
Technologies we pair it with
Tell us what is slowing your business down.
A 30-minute call with a senior engineer — not a salesperson. You leave with an architecture sketch and an honest cost range, whether or not you hire us.
Direct line
+91 70033 91355Mon–Sat · 9:30 AM – 7:30 PM IST · Sealdah, Kolkata