{"id":50423043,"url":"https://github.com/khasky/nodejs-runtime-performance-playbook","last_synced_at":"2026-05-31T09:05:54.107Z","repository":{"id":350973579,"uuid":"1208997972","full_name":"khasky/nodejs-runtime-performance-playbook","owner":"khasky","description":"Practical guide for Node.js APIs and workers: event-loop health, streaming and backpressure, memory, diagnostics, and production performance habits.","archived":false,"fork":false,"pushed_at":"2026-04-13T02:25:57.000Z","size":4,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-13T04:04:42.978Z","etag":null,"topics":["backend","diagnostics","event-loop","guide","memory","nodejs","observability","performance","playbook","runtime","streams"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/khasky.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-13T01:57:07.000Z","updated_at":"2026-04-13T02:26:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/khasky/nodejs-runtime-performance-playbook","commit_stats":null,"previous_names":["khasky/nodejs-runtime-performance-playbook"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/khasky/nodejs-runtime-performance-playbook","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khasky%2Fnodejs-runtime-performance-playbook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khasky%2Fnodejs-runtime-performance-playbook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khasky%2Fnodejs-runtime-performance-playbook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khasky%2Fnodejs-runtime-performance-playbook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/khasky","download_url":"https://codeload.github.com/khasky/nodejs-runtime-performance-playbook/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/khasky%2Fnodejs-runtime-performance-playbook/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33725111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","diagnostics","event-loop","guide","memory","nodejs","observability","performance","playbook","runtime","streams"],"created_at":"2026-05-31T09:05:53.278Z","updated_at":"2026-05-31T09:05:54.098Z","avatar_url":"https://github.com/khasky.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Node.js Runtime \u0026 Performance Playbook\n\nPractical guide for Node.js APIs and workers: event-loop health, streaming and backpressure, memory, diagnostics, and production performance habits.\n\n\u003e *If I were running a serious Node.js API or worker today, what would I care about before I cared about micro-optimizing random lines of JavaScript?*\n\nThis playbook is about production realities:\n- event-loop health;\n- worker-pool pressure;\n- streaming and backpressure;\n- memory behavior;\n- CPU hotspots;\n- shutdown discipline;\n- diagnostics you can actually use.\n\n---\n\n## Table of Contents\n\n- [Node.js Runtime \\\u0026 Performance Playbook](#nodejs-runtime--performance-playbook)\n  - [Table of Contents](#table-of-contents)\n  - [Companion playbooks](#companion-playbooks)\n  - [Philosophy](#philosophy)\n  - [The performance model that matters](#the-performance-model-that-matters)\n  - [The defaults I'd reach for first](#the-defaults-id-reach-for-first)\n  - [Event-loop rules](#event-loop-rules)\n    - [Smells](#smells)\n  - [Streams and backpressure](#streams-and-backpressure)\n    - [My default view](#my-default-view)\n    - [What usually goes wrong](#what-usually-goes-wrong)\n  - [Memory and diagnostics](#memory-and-diagnostics)\n    - [What I want available](#what-i-want-available)\n    - [Signals I care about](#signals-i-care-about)\n  - [Operational habits](#operational-habits)\n    - [The boring production habits that matter](#the-boring-production-habits-that-matter)\n    - [For jobs and workers](#for-jobs-and-workers)\n  - [Common anti-patterns](#common-anti-patterns)\n  - [Worth reading](#worth-reading)\n  - [License](#license)\n\n---\n\n## Companion playbooks\n\nThese repositories form one playbook suite:\n\n- [Auth \u0026 Identity Playbook](https://github.com/khasky/auth-identity-playbook) — sessions, tokens, OAuth, and identity boundaries across the stack\n- [Backend Architecture Playbook](https://github.com/khasky/backend-architecture-playbook) — APIs, boundaries, OpenAPI, persistence, and errors\n- [Best of JavaScript](https://github.com/khasky/best-of-javascript) — curated JS/TS tooling and stack defaults\n- [Caching Playbook](https://github.com/khasky/caching-playbook) — HTTP, CDN, and application caches; consistency and invalidation\n- [Code Review Playbook](https://github.com/khasky/code-review-playbook) — PR quality, ownership, and review culture\n- [DevOps Delivery Playbook](https://github.com/khasky/devops-delivery-playbook) — CI/CD, environments, rollout safety, and observability\n- [Engineering Lead Playbook](https://github.com/khasky/engineering-lead-playbook) — standards, RFCs, and technical leadership habits\n- [Frontend Architecture Playbook](https://github.com/khasky/frontend-architecture-playbook) — React structure, performance, and consuming API contracts\n- [Marketing and SEO Playbook](https://github.com/khasky/marketing-and-seo-playbook) — growth, SEO, experimentation, and marketing surfaces\n- [Monorepo Architecture Playbook](https://github.com/khasky/monorepo-architecture-playbook) — workspaces, package boundaries, and shared code at scale\n- **Node.js Runtime \u0026 Performance Playbook** — event loop, streams, memory, and production Node performance\n- [Testing Strategy Playbook](https://github.com/khasky/testing-strategy-playbook) — unit, integration, contract, E2E, and CI-friendly test layers\n\n---\n\n## Philosophy\n\nMost Node.js performance work is not about clever syntax tricks.\n\nIt is about:\n- not blocking the event loop;\n- not over-buffering work;\n- not pretending memory issues are \"just GC being weird\";\n- not reading huge payloads into RAM when a stream should exist;\n- measuring before rewriting.\n\n---\n\n## The performance model that matters\n\nNode.js gives you a powerful async runtime, but it is still very easy to create latency and throughput problems when CPU-heavy work, synchronous APIs, or uncontrolled concurrency pile up.\n\nMy baseline mental model:\n- the **event loop** should stay free for short, fast coordination work;\n- expensive or high-volume data movement should use **streaming** where appropriate;\n- memory growth is a production signal, not an aesthetic concern;\n- queue depth, latency, and error rates tell you more than \"it worked locally\".\n\n---\n\n## The defaults I'd reach for first\n\nIf I were building a production Node service today, I would usually start with:\n\n- **Runtime:** current supported Node LTS policy for the repo\n- **HTTP layer:** a framework that makes lifecycle hooks explicit\n- **Observability:** logs + metrics + tracing from day one\n- **Payload strategy:** streams for large files and long pipelines\n- **Diagnostics:** repeatable profiling and memory investigation workflow\n- **Shutdown:** explicit graceful termination path\n- **Concurrency:** limits, pools, and backpressure-aware design\n\n---\n\n## Event-loop rules\n\nThese rules catch a surprising amount of pain:\n\n1. **Never normalize blocking work as \"fine because it's rare\".**\n2. **Treat synchronous filesystem / crypto / compression calls carefully.**\n3. **Keep request handlers thin and short-lived.**\n4. **Cap internal concurrency instead of trusting the universe.**\n5. **Measure tail latency, not only averages.**\n\n### Smells\n\n- regexes or parsing work that spike CPU\n- giant JSON serialization in hot paths\n- retries without jitter or concurrency limits\n- synchronous startup checks leaking into request paths\n- one endpoint that allocates massive objects per request\n\n---\n\n## Streams and backpressure\n\nLarge payloads, exports, imports, uploads, ETL jobs, and proxying work should often be treated as **streaming problems**, not \"read everything first\" problems.\n\n### My default view\n\n- stream when data is large or unbounded;\n- honor backpressure;\n- avoid buffering entire files unless there is a clear business reason;\n- prefer pipeline-style flows over hand-rolled event spaghetti.\n\n### What usually goes wrong\n\n- ignoring `false` from writable writes\n- mixing flowing and paused stream assumptions blindly\n- loading entire archives / CSVs / blobs into memory\n- turning every stream into a `Buffer` \"for convenience\"\n\n---\n\n## Memory and diagnostics\n\nMemory issues in Node are rarely solved by guessing.\n\n### What I want available\n\n- heap snapshots when needed\n- CPU profiles for hot paths\n- GC traces for suspected memory pressure\n- request / job correlation to connect symptoms to workloads\n\n### Signals I care about\n\n- rising heap usage after steady-state traffic\n- GC activity climbing with latency\n- worker processes restarting due to memory pressure\n- throughput collapsing during large batch jobs\n\n---\n\n## Operational habits\n\n### The boring production habits that matter\n\n- set timeouts intentionally;\n- make outbound calls abortable;\n- instrument queues, retries, and circuit-breaker style protections;\n- cap body sizes and upload limits;\n- separate request-serving concerns from background-job concerns;\n- rehearse graceful shutdown and drain logic.\n\n### For jobs and workers\n\n- work should be idempotent where possible;\n- retry rules should be explicit;\n- poison messages should have a quarantine path;\n- job payload size should stay bounded and documented.\n\n---\n\n## Common anti-patterns\n\n- using Node as if it were a thread-per-request runtime;\n- overusing in-process memory as a durable coordination mechanism;\n- assuming \"async\" means \"safe under unlimited concurrency\";\n- doing whole-file transforms in RAM when streams fit better;\n- skipping diagnostics until the incident is already happening;\n- treating performance as a one-time benchmark instead of an operational property.\n\n---\n\n## Worth reading\n\n- [The Node.js event loop](https://nodejs.org/learn/asynchronous-work/event-loop-timers-and-nexttick)\n- [Don't block the event loop](https://nodejs.org/learn/asynchronous-work/dont-block-the-event-loop)\n- [Backpressuring in streams](https://nodejs.org/en/learn/modules/backpressuring-in-streams)\n- [How to use streams](https://nodejs.org/learn/modules/how-to-use-streams)\n- [Profiling Node.js applications](https://nodejs.org/learn/getting-started/profiling)\n- [Tracing garbage collection](https://nodejs.org/learn/diagnostics/memory/using-gc-traces.html)\n\n---\n\n## License\n\nMIT is a sensible default for a repository like this, but choose the license that fits how you want others to reuse the material.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkhasky%2Fnodejs-runtime-performance-playbook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkhasky%2Fnodejs-runtime-performance-playbook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkhasky%2Fnodejs-runtime-performance-playbook/lists"}