NodeJS sering dipilih untuk aplikasi dengan trafik tinggi karena kemampuannya menangani ribuan koneksi secara simultan.
Namun di dunia nyata, banyak aplikasi NodeJS gagal saat traffic meningkat, bukan karena NodeJS lemah, melainkan karena salah desain, salah konfigurasi, dan kurang tuning performance.
Masalah yang sering muncul:
- API tiba-tiba lambat saat traffic naik
- CPU 100% padahal request ringan
- Memory naik terus (memory leak)
- Aplikasi crash saat peak hour
- Scaling tidak memberikan dampak signifikan
Artikel ini akan membahas NodeJS performance tuning untuk high traffic secara menyeluruh, mulai dari level kode, runtime, database, network, hingga arsitektur, lengkap dengan contoh nyata yang benar-benar digunakan di production.
Contents
- 1 1. Memahami Batasan NodeJS di High Traffic
- 2 2. Cluster Mode: Menggunakan Semua Core CPU
- 3 3. Hindari Event Loop Blocking (WAJIB)
- 4 4. Database Performance Tuning
- 5 5. Cache Strategy untuk High Traffic
- 6 6. HTTP & Network Optimization
- 7 7. Memory Management & Leak Prevention
- 8 8. Logging Aman untuk High Traffic
- 9 9. Rate Limiting & Load Protection
- 10 10. Graceful Shutdown (Sangat Penting)
- 11 11. Payload Optimization
- 12 12. Load Testing (WAJIB Sebelum Production)
- 13 13. Studi Kasus Nyata
- 14 14. Checklist Production High Traffic
- 15 Kesimpulan
- 16 Related Posts
1. Memahami Batasan NodeJS di High Traffic
1.1 Single Thread & Event Loop
NodeJS menggunakan:
- Single main thread
- Event loop non-blocking
Artinya:
- Sangat cepat untuk I/O (API, DB, network)
- Sangat buruk untuk CPU-heavy task
High traffic ≠ CPU heavy.
High traffic = banyak request kecil dalam waktu bersamaan.
1.2 Contoh Kesalahan Fatal di High Traffic
app.get('/calculate', (req, res) => {
const result = heavyCalculation(); // blocking
res.json(result);
});
Dampak di production:
- Semua request lain ikut tertunda
- Event loop macet
- Latency melonjak tajam
2. Cluster Mode: Menggunakan Semua Core CPU
2.1 Masalah Default NodeJS
Secara default:
node app.js
➡️ Hanya 1 core CPU yang digunakan.
2.2 Solusi: PM2 Cluster Mode
pm2 start app.js -i max
PM2 akan:
- Menjalankan app di semua core
- Membagi traffic otomatis
- Restart process jika crash
📈 Dampak nyata di production:
- Throughput naik 2–4x
- CPU lebih stabil
- Downtime menurun drastis
3. Hindari Event Loop Blocking (WAJIB)
3.1 Contoh Blocking Code
function processData(data) {
for (let i = 0; i < 1e9; i++) {}
return data;
}
Satu request = seluruh server lambat.
3.2 Solusi 1: Worker Threads
const { Worker } = require('worker_threads');
app.get('/report', (req, res) => {
const worker = new Worker('./worker.js');
worker.on('message', data => res.json(data));
});
3.3 Solusi 2: Pisahkan ke Service Lain
Best practice SaaS:
- NodeJS → API
- Go / Python → heavy processing
- Komunikasi via queue
4. Database Performance Tuning
4.1 Kesalahan Umum: Koneksi per Request
app.get('/users', async () => {
const conn = await mysql.createConnection(config);
return conn.query('SELECT * FROM users');
});
❌ Lambat
❌ Tidak scalable
4.2 Solusi: Connection Pooling
const pool = mysql.createPool({
connectionLimit: 20,
host: 'localhost',
user: 'app'
});
app.get('/users', async () => {
const [rows] = await pool.query(
'SELECT id, name FROM users LIMIT 50'
);
return rows;
});
📉 Efek nyata:
- Latency turun drastis
- DB tidak overload saat traffic tinggi
4.3 Index Database Itu Lebih Penting dari NodeJS
90% bottleneck high traffic = database.
Pastikan:
- Index kolom WHERE
- Index foreign key
- Hindari SELECT *
5. Cache Strategy untuk High Traffic
5.1 Tanpa Cache (Masalah Besar)
app.get('/stats', async (req, res) => {
const data = await db.getStats();
res.json(data);
});
Setiap request = query mahal.
5.2 Redis Cache (Solusi Production)
app.get('/stats', async (req, res) => {
const cached = await redis.get('stats');
if (cached) {
return res.json(JSON.parse(cached));
}
const data = await db.getStats();
await redis.setex('stats', 60, JSON.stringify(data));
res.json(data);
});
📊 Hasil nyata:
- DB load turun 70–90%
- API stabil saat spike traffic
5.3 Multi-Level Cache
- CDN (Cloudflare)
- Nginx
- Redis
- In-memory
6. HTTP & Network Optimization
6.1 Aktifkan Keep-Alive
Tanpa keep-alive:
- Handshake berulang
- Latency naik
Dengan Nginx:
keepalive_timeout 65;
6.2 Compression
Gunakan:
- gzip
- brotli
Payload kecil = throughput besar.
7. Memory Management & Leak Prevention
7.1 Gejala Memory Leak
- RAM naik terus
- Tidak turun meski traffic turun
- PM2 restart berulang
7.2 Contoh Penyebab Leak
const cache = [];
app.get('/data', (req, res) => {
cache.push(req.body);
res.send('ok');
});
7.3 Atur Memory Limit
node --max-old-space-size=4096 app.js
Dengan PM2:
pm2 start app.js --max-memory-restart 2G
8. Logging Aman untuk High Traffic
8.1 Anti-Pattern Logging
fs.writeFileSync('log.txt', data);
❌ Blocking
❌ Slow
8.2 Logging Asynchronous
const pino = require('pino')();
pino.info({
userId,
action: 'login'
});
9. Rate Limiting & Load Protection
9.1 Rate Limit API
const rateLimit = require('express-rate-limit');
app.use(rateLimit({
windowMs: 60 * 1000,
max: 100
}));
Melindungi dari:
- Abuse
- Bot
- Traffic spike tidak wajar
9.2 Load Shedding
Saat overload:
- Tolak request non-kritis
- Prioritaskan core business API
10. Graceful Shutdown (Sangat Penting)
10.1 Tanpa Graceful Shutdown
- Request terputus
- Data inconsistency
10.2 Implementasi Benar
const server = app.listen(3000);
process.on('SIGTERM', () => {
console.log('Shutting down...');
server.close(() => {
process.exit(0);
});
});
11. Payload Optimization
11.1 Overfetching (Salah)
{
"id": 1,
"name": "User",
"created_at": "...",
"updated_at": "...",
"preferences": {}
}
11.2 Payload Minimal (Benar)
{
"id": 1,
"name": "User"
}
📉 Payload kecil → throughput besar.
12. Load Testing (WAJIB Sebelum Production)
12.1 Contoh Load Test dengan Autocannon
npx autocannon -c 500 -d 30 https://api.domain.com
Pantau:
- Latency p95
- Error rate
- Requests/sec
13. Studi Kasus Nyata
Kondisi Awal
- NodeJS API
- 2.000 req/detik
- Latency 1.8s
- CPU 90%
Optimasi
- PM2 cluster
- Redis cache
- DB pooling
- Rate limit
- Payload trimming
Hasil
- Latency < 200ms
- CPU stabil 50%
- Zero downtime saat peak
14. Checklist Production High Traffic
✅ NodeJS LTS
✅ Cluster mode
✅ Redis cache
✅ DB pooling
✅ Async logging
✅ Rate limit
✅ Graceful shutdown
✅ Load testing
Kesimpulan
NodeJS sangat mampu menangani high traffic, tetapi hanya jika diperlakukan sebagai sistem production yang serius.
Masalah performa hampir selalu disebabkan oleh:
- Event loop blocking
- Salah desain database
- Tidak ada cache
- Tidak ada monitoring
High traffic bukan soal framework, tapi disiplin engineering.