Skip to main content
If your Next.js application struggles under load, crashes with 200+ concurrent users, or shows uneven CPU usage across PM2 instances, you’re likely experiencing event loop blocking. This guide explains what event loops are, why they matter, and how to implement monitoring to diagnose and fix performance bottlenecks.

Table of Contents

  1. Understanding Event Loops
  2. Why Event Loops Matter for Next.js
  3. Implementing Event Loop Monitoring
  4. Interpreting Monitoring Data
  5. Common Blocking Patterns and Fixes
  6. Advanced Monitoring Setup

Understanding Event Loops

What is an Event Loop?

Node.js (and by extension, Next.js) runs on a single thread. Yet it can handle thousands of concurrent connections efficiently. The event loop makes this possible. Think of a restaurant kitchen with one chef. Instead of preparing one complete order before starting the next, the chef:
  1. Puts burger #1 on the grill
  2. While it cooks, starts burger #2
  3. While both cook, prepares fries
  4. Checks which items are done
  5. Serves completed orders
  6. Repeats
This is how Node.js works. The event loop continuously cycles through tasks, checking what’s ready to execute next.

The Event Loop Cycle

Key Point: The loop waits if a callback takes too long.

Non-Blocking vs Blocking Code

Non-Blocking (Good):
Blocking (Bad):
The blocking code prevents the event loop from processing other requests, creating a bottleneck even with available CPU capacity. The symptom will be a degraded experience for users while your resources are still not used 100%.

Why Event Loops Matter for Next.js

The PM2 Cluster Scenario

When running Next.js with PM2 in cluster mode, you typically have multiple worker processes: If one worker’s event loop is blocked by expensive synchronous operations, that worker can’t handle new requests. PM2 continues sending it requests via round-robin distribution, but they queue up, causing timeouts and poor performance.

Symptoms of Event Loop Blocking

  • One PM2 instance at 100% CPU, others underutilized
  • Requests timing out despite available server resources
  • Uneven request distribution across workers
  • Application crashes under moderate load (200+ concurrent users)
  • Response times increase dramatically under load

Implementing Event Loop Monitoring

Step 1: Create the Monitor

Create the monitoring module using Node.js’s built-in perf_hooks API to track event loop delay with high precision. Create lib/monitoring/advancedEventLoopMonitor.js:

Step 2: Initialize on Server Start

Next.js 13+ uses the instrumentation hook for server initialization. Create instrumentation.js in your project root:
Enable instrumentation in next.config.js:

Step 3: Create Health Check Endpoint

Create app/api/monitoring/health/route.js:

Step 4: Create Request Tracking Middleware

Create middleware.js in your project root:
Create app/api/[...route]/route.js wrapper to track completion:

Interpreting Monitoring Data

Understanding the Metrics

The monitor tracks several key metrics: Event Loop Delay Percentiles:
  • P50 (Median): Half of all event loop iterations complete faster than this value
  • P95: 95% of iterations complete faster than this value
  • P99: 99% of iterations complete faster than this value
Target Values:
  • P50: < 10ms (excellent), 10-25ms (good), > 25ms (investigate)
  • P95: < 50ms (excellent), 50-100ms (acceptable), > 100ms (warning)
  • P99: < 100ms (excellent), 100-250ms (warning), > 250ms (critical)

Reading the Health Report

Health Status Interpretation: 🟢 HEALTHY: P99 < 100ms
  • Application responding well
  • Event loop processing efficiently
  • No immediate action needed
🟡 WARNING: P95 > 50ms or P99 100-250ms
  • Event loop experiencing delays
  • Investigate recent code changes
  • Review slow requests log
  • Consider optimization
🔴 CRITICAL: P99 > 250ms
  • Event loop heavily blocked
  • User experience degraded
  • Immediate action required
  • Check for CPU-intensive operations

Real-World Example Analysis

Good Performance:
This shows consistent, fast event loop processing. The application handles load well. Warning Signs:
High variance between P50 and P99 indicates sporadic blocking operations. Investigate slow requests. Critical Issues:
Consistently high delays across all percentiles indicate systemic blocking issues. Check for synchronous database operations or heavy computation.

Common Blocking Patterns and Fixes

1. Large JSON Parsing

❌ Blocking:
✅ Non-Blocking:

2. Synchronous File Operations

❌ Blocking:
✅ Non-Blocking:

3. Complex Array Operations

❌ Blocking:
✅ Non-Blocking:
Or batch process:

4. Database Queries Without Connection Pooling

❌ Blocking:
✅ Non-Blocking:

Advanced Monitoring Setup

Real-Time Dashboard Script

Create scripts/monitor-dashboard.sh. Don’t forget to adapt the pm2 application name. You will also need the jq utility on your system.
Make it executable:

Load Test Monitoring

Create scripts/load-test-monitor.sh:
Run alongside your load test:

Analyzing Results

After your load test, analyze the collected data:

Best Practices

1. Set Appropriate Thresholds

Adjust thresholds based on your application:

2. Monitor in Staging First

Test your monitoring setup in a staging environment before production deployment to:
  • Verify thresholds are appropriate
  • Ensure logging doesn’t impact performance
  • Validate alerting mechanisms

3. Combine with APM Tools

Event loop monitoring complements Application Performance Monitoring tools like Blackfire.io:
  • Use event loop monitoring to identify blocking operations
  • Use APM for distributed tracing and end-to-end monitoring
  • Correlate event loop delays with external service latencies

4. Regular Performance Audits

Schedule monthly performance reviews:
  • Analyze P99 trends over time
  • Identify endpoints with degrading performance
  • Review and optimize slow requests
  • Update monitoring thresholds as needed

Conclusion

Event loop monitoring is essential for building performant Next.js applications at scale. By implementing the monitoring system described in this guide, you can:
  • Identify bottlenecks before they impact users
  • Optimize critical paths with data-driven insights
  • Scale confidently knowing your application’s limits
  • Diagnose issues quickly with detailed metrics
Remember: The event loop is the heartbeat of your Node.js application. Keep it healthy, and your application will scale smoothly.

Additional Resources

Ready to deploy your optimized Next.js application? Create a free Upsun account to get instant preview environments, Git-driven infrastructure, and built-in observability tools for production-ready deployments.
Last modified on April 27, 2026