Bootstrap a Node.js backend with ESM, typed config, graceful shutdown, and structured logging from the start. Use when starting a Node service or hardening one that grew without foundations.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add Amey-Thakur/AI-SKILLS --skill node-backend-setup --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Node Backend Setup?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/amey-thakur-node-backend-setup)More formats (shields.io, HTML) on the badges page.
---
name: node-backend-setup
description: Bootstrap a Node.js backend with ESM, typed config, graceful shutdown, and structured logging from the start. Use when starting a Node service or hardening one that grew without foundations.
---
# Node backend setup
A Node backend that starts as a quick `index.js` and grows accretes the
same missing foundations every time: no config discipline, no graceful
shutdown, console.log everywhere. Putting the foundations in at the start
costs an hour and saves a rewrite.
## Method
1. **Start with ESM and TypeScript.** `"type": "module"`, a tsconfig
targeting your Node version (see tsconfig-mastery), and a runner
(`tsx`/`ts-node` for dev, compiled output or a bundler like `tsup` for
prod). Modern Node runs TypeScript-adjacent setups cleanly; pick one
and stay consistent to avoid the module-resolution pain (see
js-modules).
2. **Load and validate config once, typed.** Read environment variables
at startup into a validated, typed config object (a schema validator:
zod/envalid), failing fast with a clear message if a required var is
missing or malformed (see environment-config, request-validation). No
`process.env.FOO` scattered through the code; one config module every
file imports.
3. **Implement graceful shutdown from day one.** Trap `SIGTERM`/`SIGINT`:
stop accepting new connections, finish in-flight requests, close the
DB pool and other resources, then exit; with a timeout that forces
exit if drain hangs (see graceful-shutdown). Every deploy and scale-in
sends SIGTERM; without this, each one drops requests.
4. **Use structured logging, not console.log.** A logger (pino/winston)
emitting JSON with levels, a request/correlation id, and no secrets
(see structured-logging, log-levels). `console.log` gives you
unsearchable, unleveled noise the moment the service sees real traffic.
5. **Add health and readiness endpoints.** A liveness check (process is
up) and a readiness check (dependencies reachable) so orchestrators
route and restart correctly (see health-checks); the difference
matters the first time a dependency blips.
6. **Handle the process-level failures.** Register `unhandledRejection`
and `uncaughtException` handlers that log and exit cleanly (a crashed
process is better than a zombie in a bad state; let the orchestrator
restart it), and never leave them unset (see js-error-handling).
## Boundaries
- This is the service skeleton; the framework choice (Express, Fastify,
Hono, Nest) and the API design sit on top (see rest-endpoint-design,
api-design). Pick the framework for the project, but the foundations
above are framework-independent.
- Clustering and multi-core scaling (Node uses one core per process) is a
deployment decision (a process manager or the orchestrator running N
replicas), usually better than the in-process `cluster` module.
- Long CPU-bound work blocks the event loop and belongs in worker threads
or a separate service, not the request path (see js-event-loop).
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!