[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"post-scaling-nodejs-single-process-distributed":3,"parsed-post-cd2d70e2-f1c3-490e-b884-d53b8d053f72":87,"header-categories":402},{"success":4,"data":5},true,{"id":6,"slug":7,"title":8,"excerpt":9,"content":10,"status":11,"visibility":12,"featuredImage":13,"canonicalUrl":14,"readingTime":15,"viewCount":16,"commentEnabled":4,"publishedAt":17,"scheduledAt":14,"createdAt":18,"updatedAt":19,"seoTitle":20,"seoDescription":9,"seoKeywords":14,"authorId":21,"author":22,"coAuthors":27,"tags":28,"categories":44,"comments":53,"_count":54,"relatedPosts":56},"cd2d70e2-f1c3-490e-b884-d53b8d053f72","scaling-nodejs-single-process-distributed","Scaling Node.js: From Single Process to Distributed System","A roadmap for scaling Node.js from handling 100 to 100,000 requests per second — clustering, load balancing, caching, and horizontal scaling.","## The Scaling Journey\n\nNode.js runs on a single thread by default. That single thread handles surprisingly well — often 10,000+ requests\u002Fsecond. But at some point, you need more.\n\n## Level 1: Optimize the Single Process\n\nBefore adding complexity, squeeze more from what you have:\n\n```typescript\n\u002F\u002F 1. Use streaming instead of buffering\napp.get('\u002Flarge-file', (req, res) => {\n  const stream = fs.createReadStream('large-file.csv')\n  stream.pipe(res) \u002F\u002F Constant memory regardless of file size\n})\n\n\u002F\u002F 2. Cache expensive operations\nconst cache = new Map\u003Cstring, { data: unknown; expires: number }>()\n\nfunction cached\u003CT>(key: string, ttl: number, fn: () => Promise\u003CT>): Promise\u003CT> {\n  const hit = cache.get(key)\n  if (hit && hit.expires > Date.now()) return hit.data as Promise\u003CT>\n\n  const result = fn()\n  result.then(data => cache.set(key, { data, expires: Date.now() + ttl }))\n  return result\n}\n\n\u002F\u002F 3. Use connection pooling\nconst pool = new Pool({\n  max: 20,              \u002F\u002F Match your CPU count\n  idleTimeoutMillis: 30000,\n  connectionTimeoutMillis: 2000,\n})\n```\n\n## Level 2: Cluster Mode\n\nUse all CPU cores:\n\n```typescript\nimport cluster from 'node:cluster'\nimport { cpus } from 'node:os'\n\nif (cluster.isPrimary) {\n  const numWorkers = cpus().length\n  console.log(`Starting ${numWorkers} workers`)\n\n  for (let i = 0; i \u003C numWorkers; i++) {\n    cluster.fork()\n  }\n\n  cluster.on('exit', (worker) => {\n    console.log(`Worker ${worker.process.pid} died, restarting...`)\n    cluster.fork()\n  })\n} else {\n  startServer()\n}\n```\n\nOr simply use PM2:\n\n```bash\npm2 start server.js -i max  # Uses all cores\n```\n\n::callout{icon=\"i-lucide-cpu\" color=\"info\"}\nClustering gives you linear scaling up to your CPU core count. A 4-core machine handles roughly 4x the traffic of a single process.\n::\n\n## Level 3: External Cache (Redis)\n\nMove caching outside the process so all instances share it:\n\n```typescript\nimport Redis from 'ioredis'\n\nconst redis = new Redis(process.env.REDIS_URL)\n\nasync function getCachedPosts(page: number) {\n  const key = `posts:page:${page}`\n  const cached = await redis.get(key)\n  if (cached) return JSON.parse(cached)\n\n  const posts = await db.post.findMany({ skip: (page - 1) * 20, take: 20 })\n  await redis.setex(key, 300, JSON.stringify(posts)) \u002F\u002F 5 min TTL\n  return posts\n}\n```\n\n## Level 4: Horizontal Scaling\n\nMultiple servers behind a load balancer:\n\n```\n                    ┌─── Node Instance 1 (4 workers)\nLoad Balancer ─────┼─── Node Instance 2 (4 workers)\n                    └─── Node Instance 3 (4 workers)\n```\n\nRequirements:\n- **Stateless servers** — No in-memory sessions\n- **External session store** — Redis\n- **Shared nothing** — Each instance is independent\n- **Health checks** — Load balancer removes unhealthy instances\n\n## Level 5: Read Replicas and Queue Workers\n\n```\nWrites ──→ Primary DB\nReads  ──→ Read Replica 1, Read Replica 2\n\nHeavy jobs ──→ Queue (BullMQ) ──→ Worker processes\n```\n\n## When to Scale What\n\n| Bottleneck | Solution |\n|-----------|----------|\n| CPU-bound | Cluster mode → more instances |\n| I\u002FO-bound | Connection pooling → async optimization |\n| Database reads | Read replicas → caching layer |\n| Database writes | Queue + batch processing |\n| Memory | Streaming → pagination → horizontal scale |\n\nDon't pre-optimize. Measure first, identify the actual bottleneck, then apply the appropriate technique.\n","published","public","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1605379399642-870262d3d051?w=1200&q=80",null,11,1025,"2026-05-10T06:04:14.278Z","2026-07-24T06:04:14.280Z","2026-07-28T13:16:51.000Z","Scaling Node.js: From Single Process to Distributed System | BitBlog","fddb5d93-7a2c-4d86-a06a-fa32e73a01c6",{"email":23,"bio":24,"id":21,"name":25,"avatarUrl":26},"mbeahessilfieprince@gmail.com","Fullstack Software Developer ","Mbeah Essilfie","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F93322394?v=4",[],[29,34,39],{"id":30,"name":31,"color":32,"description":33},"nodejs","Node.js","#339933","JavaScript runtime built on V8",{"id":35,"name":36,"color":37,"description":38},"devops","DevOps","#ff6c37","Development and Operations",{"id":40,"name":41,"color":42,"description":43},"performance","Performance","#e535ab","Web performance optimization",[45,49],{"id":46,"name":47,"description":48},"devops-cloud","DevOps & Cloud","Infrastructure, deployment, and cloud computing",{"id":50,"name":51,"description":52},"software-engineering","Software Engineering","Best practices, patterns, and principles",[],{"comments":55},0,[57,67,77],{"id":58,"slug":59,"title":60,"excerpt":61,"featuredImage":62,"viewCount":63,"readingTime":64,"publishedAt":65,"author":66},"2997028f-4d22-4eb7-9d86-894a54cb559a","building-type-safe-apis-nuxt3-prisma","Building Type-Safe APIs with Nuxt 3 and Prisma","Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1498050108023-c5249f4df085?w=1200&q=80",1921,8,"2026-07-23T06:02:46.910Z",{"id":21,"name":25,"avatarUrl":26},{"id":68,"slug":69,"title":70,"excerpt":71,"featuredImage":72,"viewCount":73,"readingTime":74,"publishedAt":75,"author":76},"da9e4553-8b0d-411e-b4ec-f9684017e163","mastering-tailwind-css-design-systems","Mastering Tailwind CSS: From Utility Classes to Design Systems","Go beyond basic utility classes and learn how to build cohesive, maintainable design systems with Tailwind CSS.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1555066931-4365d14bab8c?w=1200&q=80",256,10,"2026-07-21T06:02:49.268Z",{"id":21,"name":25,"avatarUrl":26},{"id":78,"slug":79,"title":80,"excerpt":81,"featuredImage":82,"viewCount":83,"readingTime":84,"publishedAt":85,"author":86},"50add5fc-4026-4267-b917-7f71ea9e35b0","complete-guide-vue3-composables","The Complete Guide to Vue 3 Composables","Understand the power of Vue 3's Composition API through practical, real-world composable patterns that you can use today.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1517694712202-14dd9538aa97?w=1200&q=80",989,12,"2026-07-19T06:02:51.753Z",{"id":21,"name":25,"avatarUrl":26},{"data":88,"body":90,"toc":392},{"title":89,"description":89},"",{"type":91,"children":92},"root",[93,102,108,114,119,132,138,143,151,156,166,177,183,188,196,202,207,217,222,268,274,283,289,382,387],{"type":94,"tag":95,"props":96,"children":98},"element","h2",{"id":97},"the-scaling-journey",[99],{"type":100,"value":101},"text","The Scaling Journey",{"type":94,"tag":103,"props":104,"children":105},"p",{},[106],{"type":100,"value":107},"Node.js runs on a single thread by default. That single thread handles surprisingly well — often 10,000+ requests\u002Fsecond. But at some point, you need more.",{"type":94,"tag":95,"props":109,"children":111},{"id":110},"level-1-optimize-the-single-process",[112],{"type":100,"value":113},"Level 1: Optimize the Single Process",{"type":94,"tag":103,"props":115,"children":116},{},[117],{"type":100,"value":118},"Before adding complexity, squeeze more from what you have:",{"type":94,"tag":120,"props":121,"children":126},"pre",{"className":122,"code":123,"language":124,"meta":89,"style":125},"language-typescript","\u002F\u002F 1. Use streaming instead of buffering\napp.get('\u002Flarge-file', (req, res) => {\n  const stream = fs.createReadStream('large-file.csv')\n  stream.pipe(res) \u002F\u002F Constant memory regardless of file size\n})\n\n\u002F\u002F 2. Cache expensive operations\nconst cache = new Map\u003Cstring, { data: unknown; expires: number }>()\n\nfunction cached\u003CT>(key: string, ttl: number, fn: () => Promise\u003CT>): Promise\u003CT> {\n  const hit = cache.get(key)\n  if (hit && hit.expires > Date.now()) return hit.data as Promise\u003CT>\n\n  const result = fn()\n  result.then(data => cache.set(key, { data, expires: Date.now() + ttl }))\n  return result\n}\n\n\u002F\u002F 3. Use connection pooling\nconst pool = new Pool({\n  max: 20,              \u002F\u002F Match your CPU count\n  idleTimeoutMillis: 30000,\n  connectionTimeoutMillis: 2000,\n})\n","typescript","undefined",[127],{"type":94,"tag":128,"props":129,"children":130},"code",{"__ignoreMap":89},[131],{"type":100,"value":123},{"type":94,"tag":95,"props":133,"children":135},{"id":134},"level-2-cluster-mode",[136],{"type":100,"value":137},"Level 2: Cluster Mode",{"type":94,"tag":103,"props":139,"children":140},{},[141],{"type":100,"value":142},"Use all CPU cores:",{"type":94,"tag":120,"props":144,"children":146},{"className":122,"code":145,"language":124,"meta":89,"style":125},"import cluster from 'node:cluster'\nimport { cpus } from 'node:os'\n\nif (cluster.isPrimary) {\n  const numWorkers = cpus().length\n  console.log(`Starting ${numWorkers} workers`)\n\n  for (let i = 0; i \u003C numWorkers; i++) {\n    cluster.fork()\n  }\n\n  cluster.on('exit', (worker) => {\n    console.log(`Worker ${worker.process.pid} died, restarting...`)\n    cluster.fork()\n  })\n} else {\n  startServer()\n}\n",[147],{"type":94,"tag":128,"props":148,"children":149},{"__ignoreMap":89},[150],{"type":100,"value":145},{"type":94,"tag":103,"props":152,"children":153},{},[154],{"type":100,"value":155},"Or simply use PM2:",{"type":94,"tag":120,"props":157,"children":161},{"className":158,"code":159,"language":160,"meta":89,"style":125},"language-bash","pm2 start server.js -i max  # Uses all cores\n","bash",[162],{"type":94,"tag":128,"props":163,"children":164},{"__ignoreMap":89},[165],{"type":100,"value":159},{"type":94,"tag":167,"props":168,"children":171},"callout",{"color":169,"icon":170},"info","i-lucide-cpu",[172],{"type":94,"tag":103,"props":173,"children":174},{},[175],{"type":100,"value":176},"Clustering gives you linear scaling up to your CPU core count. A 4-core machine handles roughly 4x the traffic of a single process.",{"type":94,"tag":95,"props":178,"children":180},{"id":179},"level-3-external-cache-redis",[181],{"type":100,"value":182},"Level 3: External Cache (Redis)",{"type":94,"tag":103,"props":184,"children":185},{},[186],{"type":100,"value":187},"Move caching outside the process so all instances share it:",{"type":94,"tag":120,"props":189,"children":191},{"className":122,"code":190,"language":124,"meta":89,"style":125},"import Redis from 'ioredis'\n\nconst redis = new Redis(process.env.REDIS_URL)\n\nasync function getCachedPosts(page: number) {\n  const key = `posts:page:${page}`\n  const cached = await redis.get(key)\n  if (cached) return JSON.parse(cached)\n\n  const posts = await db.post.findMany({ skip: (page - 1) * 20, take: 20 })\n  await redis.setex(key, 300, JSON.stringify(posts)) \u002F\u002F 5 min TTL\n  return posts\n}\n",[192],{"type":94,"tag":128,"props":193,"children":194},{"__ignoreMap":89},[195],{"type":100,"value":190},{"type":94,"tag":95,"props":197,"children":199},{"id":198},"level-4-horizontal-scaling",[200],{"type":100,"value":201},"Level 4: Horizontal Scaling",{"type":94,"tag":103,"props":203,"children":204},{},[205],{"type":100,"value":206},"Multiple servers behind a load balancer:",{"type":94,"tag":120,"props":208,"children":212},{"className":209,"code":211,"language":100},[210],"language-text","                    ┌─── Node Instance 1 (4 workers)\nLoad Balancer ─────┼─── Node Instance 2 (4 workers)\n                    └─── Node Instance 3 (4 workers)\n",[213],{"type":94,"tag":128,"props":214,"children":215},{"__ignoreMap":89},[216],{"type":100,"value":211},{"type":94,"tag":103,"props":218,"children":219},{},[220],{"type":100,"value":221},"Requirements:",{"type":94,"tag":223,"props":224,"children":225},"ul",{},[226,238,248,258],{"type":94,"tag":227,"props":228,"children":229},"li",{},[230,236],{"type":94,"tag":231,"props":232,"children":233},"strong",{},[234],{"type":100,"value":235},"Stateless servers",{"type":100,"value":237}," — No in-memory sessions",{"type":94,"tag":227,"props":239,"children":240},{},[241,246],{"type":94,"tag":231,"props":242,"children":243},{},[244],{"type":100,"value":245},"External session store",{"type":100,"value":247}," — Redis",{"type":94,"tag":227,"props":249,"children":250},{},[251,256],{"type":94,"tag":231,"props":252,"children":253},{},[254],{"type":100,"value":255},"Shared nothing",{"type":100,"value":257}," — Each instance is independent",{"type":94,"tag":227,"props":259,"children":260},{},[261,266],{"type":94,"tag":231,"props":262,"children":263},{},[264],{"type":100,"value":265},"Health checks",{"type":100,"value":267}," — Load balancer removes unhealthy instances",{"type":94,"tag":95,"props":269,"children":271},{"id":270},"level-5-read-replicas-and-queue-workers",[272],{"type":100,"value":273},"Level 5: Read Replicas and Queue Workers",{"type":94,"tag":120,"props":275,"children":278},{"className":276,"code":277,"language":100},[210],"Writes ──→ Primary DB\nReads  ──→ Read Replica 1, Read Replica 2\n\nHeavy jobs ──→ Queue (BullMQ) ──→ Worker processes\n",[279],{"type":94,"tag":128,"props":280,"children":281},{"__ignoreMap":89},[282],{"type":100,"value":277},{"type":94,"tag":95,"props":284,"children":286},{"id":285},"when-to-scale-what",[287],{"type":100,"value":288},"When to Scale What",{"type":94,"tag":290,"props":291,"children":292},"table",{},[293,312],{"type":94,"tag":294,"props":295,"children":296},"thead",{},[297],{"type":94,"tag":298,"props":299,"children":300},"tr",{},[301,307],{"type":94,"tag":302,"props":303,"children":304},"th",{},[305],{"type":100,"value":306},"Bottleneck",{"type":94,"tag":302,"props":308,"children":309},{},[310],{"type":100,"value":311},"Solution",{"type":94,"tag":313,"props":314,"children":315},"tbody",{},[316,330,343,356,369],{"type":94,"tag":298,"props":317,"children":318},{},[319,325],{"type":94,"tag":320,"props":321,"children":322},"td",{},[323],{"type":100,"value":324},"CPU-bound",{"type":94,"tag":320,"props":326,"children":327},{},[328],{"type":100,"value":329},"Cluster mode → more instances",{"type":94,"tag":298,"props":331,"children":332},{},[333,338],{"type":94,"tag":320,"props":334,"children":335},{},[336],{"type":100,"value":337},"I\u002FO-bound",{"type":94,"tag":320,"props":339,"children":340},{},[341],{"type":100,"value":342},"Connection pooling → async optimization",{"type":94,"tag":298,"props":344,"children":345},{},[346,351],{"type":94,"tag":320,"props":347,"children":348},{},[349],{"type":100,"value":350},"Database reads",{"type":94,"tag":320,"props":352,"children":353},{},[354],{"type":100,"value":355},"Read replicas → caching layer",{"type":94,"tag":298,"props":357,"children":358},{},[359,364],{"type":94,"tag":320,"props":360,"children":361},{},[362],{"type":100,"value":363},"Database writes",{"type":94,"tag":320,"props":365,"children":366},{},[367],{"type":100,"value":368},"Queue + batch processing",{"type":94,"tag":298,"props":370,"children":371},{},[372,377],{"type":94,"tag":320,"props":373,"children":374},{},[375],{"type":100,"value":376},"Memory",{"type":94,"tag":320,"props":378,"children":379},{},[380],{"type":100,"value":381},"Streaming → pagination → horizontal scale",{"type":94,"tag":103,"props":383,"children":384},{},[385],{"type":100,"value":386},"Don't pre-optimize. Measure first, identify the actual bottleneck, then apply the appropriate technique.",{"type":94,"tag":388,"props":389,"children":390},"style",{},[391],{"type":100,"value":89},{"title":89,"searchDepth":393,"depth":393,"links":394},2,[395,396,397,398,399,400,401],{"id":97,"depth":393,"text":101},{"id":110,"depth":393,"text":113},{"id":134,"depth":393,"text":137},{"id":179,"depth":393,"text":182},{"id":198,"depth":393,"text":201},{"id":270,"depth":393,"text":273},{"id":285,"depth":393,"text":288},{"success":4,"data":403},{"items":404,"pagination":461},[405,413,421,429,437,445,450,454],{"id":406,"name":407,"description":408,"parentId":14,"createdAt":409,"updatedAt":409,"parent":14,"children":410,"_count":411},"ai-future","AI & The Future","Artificial intelligence and emerging technology","2026-07-24T06:02:45.990Z",[],{"posts":412},1,{"id":414,"name":415,"description":416,"parentId":14,"createdAt":417,"updatedAt":417,"parent":14,"children":418,"_count":419},"tools-productivity","Tools & Productivity","Developer tools and workflow optimization","2026-07-24T06:02:45.712Z",[],{"posts":420},7,{"id":422,"name":423,"description":424,"parentId":14,"createdAt":425,"updatedAt":425,"parent":14,"children":426,"_count":427},"career","Career & Growth","Professional development for developers","2026-07-24T06:02:45.486Z",[],{"posts":428},3,{"id":430,"name":431,"description":432,"parentId":14,"createdAt":433,"updatedAt":433,"parent":14,"children":434,"_count":435},"opinion","Opinion & Analysis","Industry analysis and technical opinions","2026-07-24T06:02:45.272Z",[],{"posts":436},6,{"id":438,"name":439,"description":440,"parentId":14,"createdAt":441,"updatedAt":441,"parent":14,"children":442,"_count":443},"tutorials","Tutorials","Step-by-step learning guides","2026-07-24T06:02:44.965Z",[],{"posts":444},21,{"id":50,"name":51,"description":52,"parentId":14,"createdAt":446,"updatedAt":446,"parent":14,"children":447,"_count":448},"2026-07-24T06:02:44.689Z",[],{"posts":449},24,{"id":46,"name":47,"description":48,"parentId":14,"createdAt":451,"updatedAt":451,"parent":14,"children":452,"_count":453},"2026-07-24T06:02:44.453Z",[],{"posts":436},{"id":455,"name":456,"description":457,"parentId":14,"createdAt":458,"updatedAt":458,"parent":14,"children":459,"_count":460},"web-development","Web Development","Frontend and backend web development tutorials and guides","2026-07-24T06:02:44.169Z",[],{"posts":449},{"page":412,"limit":64,"total":64,"totalPages":412,"hasNext":462,"hasPrev":462},false]