Loading · Node.js
Stack Innovations/ Services/ Custom Development/ Node.js
03 / 08 · Custom Development
000Booting Node.js

Node

Bespoke Node.js services, engineered for the ten-year arc.

Start a build
The argument

A Node service is just an event loop that never blocks.

Each handler · non-blocking. Each await · a checkpoint. Each tick · work cleared.
02 — Ecosystem

Node.js,
and the right neighbours.

Framework/01
Fastify

Schema-first, low-overhead HTTP framework, our default for new services. JSON-schema validation and serialization built into the request lifecycle.

Schema-firstPluginsLow overhead
Runtime/02
Node 22 LTS

Native test runner, built-in .env support, the latest V8 JIT.

LTSV8
API layer/03
tRPC

End-to-end typesafe APIs without a schema language.

TSRPC
Data layer/04
Prisma

Type-safe queries generated from one schema file.

ORMMigrations
Validation/05
Zod

Runtime schema validation that doubles as your TypeScript types.

SchemaInferred
Queue/06
BullMQ

Redis-backed jobs, retries, and cron-style scheduling.

RedisRetries
Realtime/07
Socket.IO

WebSockets with automatic fallback and room semantics.

WSRooms
Testing/08
Vitest

Fast unit and integration tests, one runner end to end.

UnitIntegration
Deploy/09
Docker

Containerized services, identical environments dev to prod.

ContainersParity
Observability/10
OpenTelemetry

Distributed tracing across every service boundary. Vendor-neutral instrumentation that follows a request through every hop, not just the ones we own.

TracingMetricsLogs
Logging/11
pino

Structured JSON logs at line-rate, built for production.

JSONFast
03 — What we build

Three shapes,
one runtime.

01 — APIs
APIs &
services.

REST, GraphQL, or tRPC backends. Auth, rate limiting, and webhooks wired in from the first endpoint.

  • REST/GraphQL/tRPC · typed end to endFastify
  • Auth · sessions, tokens, scopesOIDC
  • Rate limiting · per route, per keyRedis
  • Webhooks · signed, retried, loggedHMAC
POST /api/orders schema.parse(body) handler(req, reply)
02 — Realtime
Realtime
systems.

WebSocket servers, live dashboards, chat and presence, pub/sub fan-out that holds at scale.

  • WebSocket servers · room-scopedSocket.IO
  • Live dashboards · push, not pollSSE/WS
  • Chat & presence · typed eventsRedis adapter
  • Pub/sub fan-out · multi-instanceRedis
ws A B C
03 — Background
Background
processing.

Job queues, ETL pipelines, scheduled workers, webhook retry — the work that happens after the response is sent.

  • Job queues · concurrency-controlledBullMQ
  • ETL pipelines · scheduled, idempotentCron
  • Scheduled workers · backed off on failRepeatable
  • Webhook retry · exponential backoffDLQ
queue done
/ Phase 01 · Discover

Listen first.

Stakeholder interviews, support tickets, traffic patterns. We map the service boundaries by mapping the work.

Discovery docTech auditRisk map
SCOPE TRAFFIC DATA TEAM RISK OUTCOME
src/ routes/orders.ts plugins/auth.ts plugins/rate-limit.ts lib/queue.ts lib/db.ts server.ts
// orders.schema.ts const Order = z.object({ id: z.string().uuid(), status: z.enum([...]), total: z.number().positive(), }); export const orderRouter = router({ create: procedure .input(Order) .mutation(...) }); → inferred client types → validated at the edge
// routes/orders.ts fastify.post('/orders', { schema: { body: Order }, }, async (req, reply) => { const order = await db .order.create({ ...req.body }) return reply.code(201).send(order) }) → shipped behind a feature flag → traced · OpenTelemetry span → tested · vitest + supertest
w1 w6 w12 +38% throughput
01
01
05
05 — Architecture

A request,
end to end.

// live · POST /api/orders
Request Static
Client Node consumer fetch · tRPC client Edge / LB Load balancer ~8ms hop Node service Fastify · event loop Zod · auth · routes Postgres + Redis Prisma · BullMQ Read replicas Observability OpenTelemetry Logs · Traces · Metrics
Client → LB~8ms
LB → Service~14ms
Service → DB~6ms
Round-trip · p9558ms
06 — Numbers

Standards,
not anecdotes.

What every Node.js build leaves with — the floor, not the ceiling.

p99 latency 0 ms · across last 12 builds
#StandardFloorMethod
01 p99 latencyproduction · cold 0ms RUM
02 Req/secsingle instance 0 load test
03 Test coveragevitest · lines 0% CI
04 Type coveragestrict mode 0% tsc
05 Critical vulnsnpm audit / Snyk 0 CI gate
06 Median design → readyendpoint-to-endpoint 0d linear
08 — Engagement

Three ways
to start.

01 / Sprint2 weeks
Diagnostic
sprint.
flatfixed scope
  • Tech audit · current Node stack
  • Architecture proposal
  • Risk & cost map
  • Live walkthrough · written report
Book a sprint
02 / MVP— Most chosen
MVP ship.
retainer4–8 weeks
  • One service surface, end to end
  • Auth · Queue · Telemetry wired
  • API contract seed · typed end to end
  • CI/CD · monitoring · runbook
  • Two rounds of post-launch iteration
Start an MVP
03 / Build12+ weeks
Ground-up
platform.
retainerquarterly
  • Multi-service platform
  • Internal admin + public API
  • Embedded design partner
  • Hand-off plan, onboarded team
Plan a build
09 — Questions

Things people
actually ask.

Node wins when the work is I/O-bound and the team is already shipping TypeScript on the frontend — one language, one type system, shared validation schemas across client and server. Go takes over when you need raw CPU throughput or a single static binary; Python takes over when the work leans on its data/ML ecosystem. For typical API, realtime, and background-job workloads, Node's non-blocking I/O model and npm ecosystem usually win on time-to-ship.
Fastify, by default. It's schema-first — request and response validation, plus serialization, are built into the framework rather than bolted on — and its plugin encapsulation model keeps large codebases from turning into middleware soup. We reach for Express only on brownfield projects already built around it, where a rewrite isn't worth the risk.
BullMQ on Redis for anything that needs retries, delays, rate limiting, or cron-style scheduling — webhook delivery, email sends, ETL steps. Jobs are idempotent by design so a retry after a crash never double-processes. We separate the job processor into its own deployable so a queue backlog never starves the API's event loop.
tRPC when both client and server are TypeScript — it gives end-to-end type inference with zero codegen and zero schema language to maintain. REST when the API has external or third-party consumers who need a stable, documented contract. GraphQL when clients need to shape their own queries across a genuinely graph-like data model — we don't reach for it just because it's available.
Yes — most of our work is brownfield. We start with a tech audit: Node version, framework, dependency health, test coverage, and where `any` or untyped boundaries hide. We ship into the existing app behind feature flags and migrate incrementally; no big-bang rewrites unless the codebase genuinely can't be salvaged.
Vitest for unit and integration tests, against the same TypeScript config as the app. Supertest-style HTTP assertions for route-level coverage, and BullMQ's test utilities for job processors. CI runs the full suite plus `npm audit`/Snyk on every PR; nothing merges with a red build or an unaddressed critical vulnerability.
10 — Start

Let's build
something worth shipping.

Two-week diagnostic, four-week MVP, twelve-week ground-up. Bring the brief — we'll send a plan, not a pitch deck.

Start a project
Tweaks
Accent
Motion
Lenis
Sound