Overview
TailStack uses Node.js clustering to maximize performance by utilizing all available CPU cores. The cluster implementation automatically spawns worker processes and handles worker lifecycle management.Why Clustering?
Node.js runs single-threaded by default. Clustering enables:- Multi-core utilization - Use all CPU cores on your server
- Better performance - Handle more concurrent requests
- Automatic failover - Workers are restarted if they crash
- Zero-downtime updates - Rolling restarts for deployments
On a 4-core machine, clustering can improve throughput by up to 4x compared to a single Node.js process.
Cluster Implementation
The cluster logic is implemented incluster/index.ts:
packages/core/source/Server/src/cluster/index.ts
How It Works
Primary Process Check
The code checks if the current process is the primary (master) process using
cluster.isPrimary.Worker Spawning
The primary process spawns worker processes equal to the number of CPU cores using
availableParallelism().Configuration
Cluster behavior is configured through constants:packages/core/source/Server/src/constant/cluster.ts
Number of Workers
By default, TailStack spawns one worker per CPU core. You can override this with theWORKERS environment variable:
.env
Worker Lifecycle
When you start the server, you’ll see output like this:Worker Crash Handling
If a worker crashes, the cluster automatically restarts it:Load Balancing
The Node.js cluster module automatically distributes incoming connections across workers using a round-robin approach (on most platforms). This provides:- Even distribution of requests
- Better resource utilization
- Improved response times under load
The operating system’s scheduler handles the round-robin distribution automatically - no additional configuration needed.
Development vs Production
You can use different worker counts for development and production:.env.development
.env.production
Alternative Cluster Manager
TailStack also includes an alternative cluster manager implementation:packages/node/src/cluster/cluster.manager.ts
- Easy access to cluster state with
isPrimary - Worker spawning with
spawnWorkers() - Worker ID retrieval with
getWorkerId()
Best Practices
Use all CPU cores in production
Use all CPU cores in production
Always use all available CPU cores in production for maximum throughput. The default configuration handles this automatically.
Limit workers in development
Limit workers in development
Use fewer workers in development (e.g., 2) to reduce resource usage and make debugging easier.
Monitor worker health
Monitor worker health
Implement health checks and monitoring to detect when workers are restarting frequently, which may indicate application bugs.
Stateless workers
Stateless workers
Keep worker processes stateless. Use Redis or a database for shared state, as workers don’t share memory.
Next Steps
Server Setup
Learn about the server initialization and app configuration
Configuration
Configure workers and other environment variables