Node.js Worker Threads for CPU Tasks

When to use CPU-bound tasks (crypto, compression, image/video processing) that would block event loop. Avoid for short, tiny tasks—overhead may outweigh benefit. Patterns Use a pool (e.g., piscina/workerpool) with bounded size; queue tasks. Pass data via Transferable when large buffers; avoid heavy serialization. Propagate cancellation/timeouts; surface errors to main thread. Observability Track queue length, task duration, worker utilization, crashes. Monitor event loop lag to confirm offload benefits. Safety Validate inputs in main thread; avoid untrusted code in workers. Cleanly shut down pool on SIGTERM; drain and close workers. Checklist CPU tasks isolated to workers; pool sized to cores. Transferables used for big buffers; timeouts set. Metrics for queue/utilization/errors in place.

March 18, 2025 · 4497 views

Scaling Node.js: Fastify vs Express

Performance notes Fastify: schema-driven, AJV validation, low-overhead routing; typically better RPS and lower p99s. Express: mature ecosystem; middleware can add overhead; great for quick prototypes. Bench considerations Compare with same validation/parsing; disable unnecessary middleware in Express. Test under keep-alive and HTTP/1.1 & HTTP/2 where applicable. Measure event loop lag and heap; not just RPS. Migration tips Start new services with Fastify; for existing Express apps, migrate edge routes first. Replace middleware with hooks/plugins; map Express middlewares to Fastify equivalents. Validate payloads with JSON schema for speed and safety. Operational tips Use pino (Fastify default) for structured logs; avoid console log overhead. Keep plugin count minimal; watch async hooks cost. Load test with realistic payload sizes; profile hotspots before/after migration. Takeaway: Fastify wins on raw throughput and structured DX; Express still fine for smaller apps, but performance-critical services benefit from Fastify’s lower overhead.

March 2, 2025 · 4269 views

Node.js Event Loop Internals (2024)

Phases refresher timers → pending → idle/prepare → poll → check → close callbacks. Microtasks (Promises/queueMicrotask) run after each phase; process.nextTick runs before microtasks. Pitfalls Long JS on main thread blocks poll → delays I/O; move CPU work to worker threads. nextTick storms can starve I/O; prefer setImmediate when deferring. Unhandled rejections crash (from Node 15+ default); handle globally in prod. Debugging NODE_DEBUG=async_hooks or --trace-events-enabled --trace-event-categories node.async_hooks. Measure event loop lag: perf_hooks.monitorEventLoopDelay(). Profile CPU with node --inspect + Chrome DevTools; use flamegraphs for hotspots. Practices Limit synchronous JSON/crypto/zlib; offload to worker threads or native modules. Keep microtask chains short; avoid deep promise recursion. Use AbortController for cancellable I/O; always clear timers. Checklist Monitor event loop lag & heap usage. Worker pool sized for CPU tasks; main loop kept light. Errors and rejections centrally handled; graceful shutdown in place.

September 18, 2024 · 3677 views

Node.js Redis Caching Patterns

Keys & TTLs Namespaced keys: app:domain:entity:id. Set TTLs per data volatility; use jitter to avoid thundering expirations. Version keys on schema changes to prevent stale reads. Stampede protection Use SETNX/lock around rebuild; short lock TTL with fallback. Serve stale-while-revalidate: return cached value, refresh asynchronously. Serialization & size Prefer JSON with bounded fields; compress only large blobs. Avoid massive lists/hashes; paginate or split keys. Operations Monitor hit rate, command latency, memory, evictions. Use connection pooling; set timeouts and retries with backoff. Cluster/replica for HA; read from replicas if consistency allows. Checklist Keys versioned; TTLs with jitter. Stampede controls in place. Metrics for hit/miss/latency/evictions; alerts configured.

August 9, 2024 · 4296 views

Node.js + Postgres Performance Tuning

Pooling Use a pool (pg/pgbouncer); size = (CPU * 2–4) per app instance; avoid per-request connections. For PgBouncer in transaction mode, avoid session features (temp tables, session prep statements). Query hygiene Parameterize queries; prevent plan cache thrash; set statement timeout. Add indexes; avoid wild % patterns; paginate with keyset when possible. Monitor slow queries; cap max rows returned; avoid huge JSON blobs. App settings Set statement_timeout, idle_in_transaction_session_timeout. Use prepared statements judiciously; for PgBouncer, prefer server-prepared off or use pgbouncer session mode. Pool instrumentation: queue wait time, checkout latency, timeouts. OS/DB basics Keep Postgres on same AZ/region; latency kills. Tune work_mem, shared_buffers, effective_cache_size appropriately (DB side). Use EXPLAIN (ANALYZE, BUFFERS) in staging for heavy queries. Checklist Pool sized and monitored; PgBouncer for many short connections. Query timeouts set; slow logs monitored. Key indexes present; pagination optimized. App-level metrics for pool wait, query latency, error rates.

July 7, 2024 · 4537 views