Performa Node.js: Event Loop, Clustering, dan Optimasi di Tahun 2026

Panduan lengkap tentang performa Node.js mencakup mekanisme event loop, clustering multi-proses, worker threads, optimasi memori, dan monitoring produksi dengan OpenTelemetry. Dilengkapi contoh kode siap pakai untuk wawancara teknis dan penerapan di lingkungan produksi.

Diagram performa Node.js menampilkan fase event loop, arsitektur clustering, dan strategi optimasi

Node.js telah menjadi fondasi utama bagi ribuan layanan backend berskala besar di seluruh dunia. Arsitektur event-driven dan model single-threaded yang dimilikinya memungkinkan penanganan puluhan ribu koneksi secara bersamaan tanpa overhead pembuatan thread untuk setiap permintaan. Namun, kemampuan tersebut baru tercapai secara optimal ketika pengembang memahami secara mendalam bagaimana event loop bekerja, kapan harus menerapkan clustering, dan teknik optimasi apa yang relevan untuk lingkungan produksi.

Di tahun 2026, dengan hadirnya Node.js 24 LTS dan peningkatan signifikan pada V8 engine, lanskap performa Node.js mengalami perubahan penting. Fitur-fitur baru seperti peningkatan performa garbage collector, stabilisasi Permission Model, dan penyempurnaan diagnostics channel membuka peluang optimasi yang sebelumnya tidak tersedia. Artikel ini membahas secara komprehensif setiap aspek performa Node.js -- mulai dari mekanisme internal event loop hingga strategi monitoring di lingkungan produksi -- disertai contoh kode yang dapat langsung diterapkan.

Pemahaman mendalam tentang topik-topik ini bukan sekadar kebutuhan teknis harian. Dalam sesi wawancara teknis untuk posisi backend engineer, pertanyaan seputar event loop, clustering, dan optimasi performa Node.js merupakan materi yang sangat sering diujikan. Penguasaan konsep-konsep ini memberikan keunggulan kompetitif yang nyata.

Poin Penting

Performa Node.js ditentukan oleh tiga pilar utama: pemahaman fase-fase event loop untuk mencegah blocking, penerapan clustering dan worker threads untuk memanfaatkan seluruh inti CPU, serta monitoring berkelanjutan menggunakan instrumentasi seperti OpenTelemetry. Menguasai ketiganya adalah kunci membangun layanan backend yang tangguh dan responsif.

Memahami Event Loop Node.js Secara Mendalam

Event loop adalah jantung dari runtime Node.js. Berbeda dengan server tradisional yang membuat thread baru untuk setiap koneksi masuk, Node.js menggunakan satu thread utama yang secara terus-menerus menjalankan siklus fase-fase tertentu. Setiap fase memiliki antrian callback yang menunggu untuk dieksekusi.

Urutan fase-fase dalam event loop adalah sebagai berikut:

  1. Timers -- mengeksekusi callback dari setTimeout dan setInterval yang telah melewati batas waktu
  2. Pending Callbacks -- mengeksekusi callback I/O yang ditunda dari iterasi sebelumnya
  3. Idle/Prepare -- fase internal yang digunakan oleh Node.js
  4. Poll -- mengambil event I/O baru dan mengeksekusi callback terkait I/O
  5. Check -- mengeksekusi callback dari setImmediate
  6. Close Callbacks -- mengeksekusi callback penutupan seperti socket.on('close')

Di antara setiap transisi fase, Node.js memproses microtask queue yang terdiri dari callback process.nextTick dan Promise yang telah resolved. Perilaku ini krusial untuk dipahami karena microtask selalu diproses sebelum event loop melanjutkan ke fase berikutnya.

Berikut adalah demonstrasi urutan eksekusi fase-fase tersebut:

event-loop-phases.jsjavascript
// Demonstrating phase execution order

const fs = require('fs');

// Phase 1: Timers — executes setTimeout/setInterval callbacks
setTimeout(() => console.log('1. Timer phase'), 0);

// Phase 4: Poll — executes I/O callbacks
fs.readFile(__filename, () => {
  console.log('2. Poll phase (I/O callback)');

  // Phase 5: Check — executes setImmediate callbacks
  setImmediate(() => console.log('3. Check phase (setImmediate)'));

  // Phase 1 again: Timer scheduled from within I/O
  setTimeout(() => console.log('4. Timer phase (from I/O)'), 0);
});

// Microtask — runs between every phase transition
Promise.resolve().then(() => console.log('Microtask: Promise'));
process.nextTick(() => console.log('Microtask: nextTick'));

Dari kode di atas, process.nextTick selalu dieksekusi sebelum Promise karena nextTick queue diproses terlebih dahulu dalam setiap iterasi microtask. Memahami urutan ini sangat penting saat mendesain sistem yang memerlukan kontrol presisi terhadap waktu eksekusi callback.

Monitoring Event Loop di Lingkungan Produksi

Mengetahui bahwa event loop terblokir adalah langkah pertama dalam mendiagnosis masalah performa. Node.js menyediakan modul perf_hooks yang memungkinkan pemantauan latensi event loop dengan resolusi tinggi. Metrik ini menjadi indikator utama kesehatan sebuah aplikasi Node.js.

Event loop utilization (ELU) mengukur rasio waktu yang dihabiskan event loop dalam kondisi aktif dibandingkan idle. Nilai ELU mendekati 1.0 mengindikasikan bahwa event loop hampir tidak pernah menganggur -- situasi yang mengkhawatirkan karena permintaan baru harus menunggu lebih lama untuk diproses.

event-loop-monitor.jsjavascript
// Production-grade event loop monitoring

const { performance, monitorEventLoopDelay } = require('perf_hooks');

// High-resolution event loop delay histogram
const histogram = monitorEventLoopDelay({ resolution: 20 });
histogram.enable();

// Track utilization over intervals
let previous = performance.eventLoopUtilization();

setInterval(() => {
  const current = performance.eventLoopUtilization(previous);
  previous = performance.eventLoopUtilization();

  const metrics = {
    // Ratio of time the loop spent active vs idle (0-1)
    utilization: current.utilization.toFixed(3),
    // Delay percentiles in milliseconds
    p50: (histogram.percentile(50) / 1e6).toFixed(2),
    p99: (histogram.percentile(99) / 1e6).toFixed(2),
    max: (histogram.max / 1e6).toFixed(2),
  };

  // Alert when utilization exceeds 70% or p99 > 100ms
  if (current.utilization > 0.7 || histogram.percentile(99) > 100e6) {
    console.warn('EVENT_LOOP_SATURATED', metrics);
  }

  histogram.reset();
}, 5000);

Dalam praktik produksi, ambang batas ELU sebesar 0.7 (70%) dan latensi p99 di atas 100ms merupakan sinyal peringatan yang memerlukan investigasi segera. Metrik-metrik ini sebaiknya dikirimkan ke sistem monitoring terpusat untuk memungkinkan pembuatan alert dan analisis tren historis.

Pola Blocking dan Solusinya

Event loop yang terblokir adalah musuh utama performa Node.js. Operasi sinkron yang memakan waktu lama pada thread utama akan menghentikan pemrosesan seluruh permintaan lain yang sedang menunggu. Dua penyebab paling umum adalah parsing JSON berukuran besar dan operasi kriptografi sinkron.

Berikut adalah pola-pola yang harus dihindari beserta solusi yang tepat:

blocking-patterns.jsjavascript
// Anti-patterns and their solutions

// PROBLEM: JSON.parse blocks on large payloads
const largePayload = Buffer.alloc(50 * 1024 * 1024); // 50MB
// JSON.parse(largePayload.toString()); // Blocks event loop 200-500ms

// SOLUTION: Stream-parse large JSON with a streaming parser
const { Transform } = require('stream');
const JSONStream = require('jsonstream2');

function processLargeJSON(readableStream) {
  return new Promise((resolve, reject) => {
    const results = [];
    readableStream
      .pipe(JSONStream.parse('items.*'))  // Stream-parse array items
      .on('data', (item) => results.push(item))
      .on('end', () => resolve(results))
      .on('error', reject);
  });
}

// PROBLEM: Synchronous crypto in request path
// const hash = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512');

// SOLUTION: Use async variant
const crypto = require('crypto');
async function hashPassword(password, salt) {
  return new Promise((resolve, reject) => {
    crypto.pbkdf2(password, salt, 100000, 64, 'sha512', (err, key) => {
      if (err) reject(err);
      else resolve(key.toString('hex'));
    });
  });
}

Prinsip dasarnya sederhana: setiap operasi yang memakan waktu lebih dari 1-2 milidetik pada thread utama harus dipindahkan ke varian asinkron atau didelegasikan ke worker thread. Parsing JSON berukuran besar sebaiknya dilakukan secara streaming, sementara operasi kriptografi harus selalu menggunakan API asinkron yang disediakan oleh modul crypto.

Siap menguasai wawancara Node.js / NestJS Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Clustering: Memanfaatkan Seluruh Inti CPU

Node.js secara bawaan berjalan pada satu inti CPU. Pada server modern yang memiliki 8, 16, atau bahkan 64 inti, menjalankan satu proses Node.js berarti membuang sebagian besar kapasitas komputasi yang tersedia. Modul cluster mengatasi keterbatasan ini dengan memungkinkan pembuatan beberapa proses worker yang berbagi port yang sama.

Arsitektur clustering terdiri dari satu proses primary yang bertugas mengelola worker dan mendistribusikan koneksi masuk. Setiap worker adalah proses Node.js terpisah dengan event loop-nya sendiri, sehingga crash pada satu worker tidak memengaruhi worker lainnya.

cluster-setup.jsjavascript
// Production clustering with graceful shutdown

const cluster = require('cluster');
const os = require('os');
const process = require('process');

const WORKER_COUNT = parseInt(process.env.WORKERS) || os.cpus().length;

if (cluster.isPrimary) {
  console.log(`Primary ${process.pid} starting ${WORKER_COUNT} workers`);

  // Fork workers for each CPU core
  for (let i = 0; i < WORKER_COUNT; i++) {
    cluster.fork();
  }

  // Restart crashed workers automatically
  cluster.on('exit', (worker, code, signal) => {
    if (!worker.exitedAfterDisconnect) {
      console.error(`Worker ${worker.process.pid} died (${signal || code}). Restarting...`);
      cluster.fork();
    }
  });

  // Graceful shutdown on SIGTERM
  process.on('SIGTERM', () => {
    console.log('Primary received SIGTERM. Shutting down workers...');
    for (const id in cluster.workers) {
      cluster.workers[id].disconnect();
    }
  });
} else {
  // Worker process — start the actual HTTP server
  const http = require('http');
  const server = http.createServer((req, res) => {
    res.writeHead(200);
    res.end(`Handled by worker ${process.pid}\n`);
  });

  server.listen(3000, () => {
    console.log(`Worker ${process.pid} listening on port 3000`);
  });

  // Graceful shutdown for individual worker
  process.on('SIGTERM', () => {
    server.close(() => process.exit(0));
  });
}

Graceful shutdown merupakan aspek yang sering diabaikan namun sangat krusial. Ketika proses primary menerima sinyal SIGTERM, setiap worker harus menyelesaikan permintaan yang sedang diproses sebelum berhenti. Pendekatan ini mencegah terputusnya koneksi klien selama proses deployment atau scaling.

Dalam praktiknya, jumlah worker yang optimal biasanya sama dengan jumlah inti CPU yang tersedia. Namun, untuk aplikasi yang bersifat I/O-intensive, penggunaan worker melebihi jumlah inti CPU dapat memberikan manfaat karena setiap worker sering berada dalam kondisi idle menunggu respons I/O.

Worker Threads: Komputasi Paralel Tanpa Proses Terpisah

Berbeda dengan clustering yang membuat proses terpisah, worker threads memungkinkan eksekusi kode JavaScript secara paralel dalam proses yang sama. Worker threads ideal untuk tugas-tugas CPU-intensive seperti pemrosesan gambar, kompresi data, atau kalkulasi kompleks yang akan memblokir event loop jika dijalankan pada thread utama.

Implementasi worker pool yang dapat digunakan kembali memberikan abstraksi yang bersih untuk mendelegasikan tugas berat:

worker-pool.jsjavascript
// Reusable worker thread pool for CPU tasks

const { Worker } = require('worker_threads');
const os = require('os');

class WorkerPool {
  constructor(workerScript, poolSize = os.cpus().length) {
    this.workers = [];
    this.queue = [];

    for (let i = 0; i < poolSize; i++) {
      this.workers.push({ busy: false, worker: new Worker(workerScript) });
    }
  }

  execute(taskData) {
    return new Promise((resolve, reject) => {
      const available = this.workers.find(w => !w.busy);

      if (available) {
        this._runTask(available, taskData, resolve, reject);
      } else {
        // Queue task until a worker is free
        this.queue.push({ taskData, resolve, reject });
      }
    });
  }

  _runTask(entry, taskData, resolve, reject) {
    entry.busy = true;
    entry.worker.postMessage(taskData);

    const onMessage = (result) => {
      entry.busy = false;
      cleanup();
      resolve(result);
      this._processQueue();
    };

    const onError = (err) => {
      entry.busy = false;
      cleanup();
      reject(err);
      this._processQueue();
    };

    const cleanup = () => {
      entry.worker.removeListener('message', onMessage);
      entry.worker.removeListener('error', onError);
    };

    entry.worker.on('message', onMessage);
    entry.worker.on('error', onError);
  }

  _processQueue() {
    if (this.queue.length === 0) return;
    const available = this.workers.find(w => !w.busy);
    if (available) {
      const { taskData, resolve, reject } = this.queue.shift();
      this._runTask(available, taskData, resolve, reject);
    }
  }
}

module.exports = { WorkerPool };

Berikut adalah contoh worker thread yang melakukan pemrosesan gambar menggunakan library sharp:

image-worker.jsjavascript
// Worker thread for CPU-intensive image processing

const { parentPort } = require('worker_threads');
const sharp = require('sharp');

parentPort.on('message', async ({ inputPath, width, height }) => {
  const result = await sharp(inputPath)
    .resize(width, height)
    .webp({ quality: 80 })
    .toBuffer();

  parentPort.postMessage({ size: result.length, buffer: result });
});

Pola ini memisahkan tugas berat dari thread utama secara efektif. Thread utama tetap responsif terhadap permintaan HTTP masuk, sementara pemrosesan gambar berjalan secara paralel pada worker thread terpisah. Mekanisme antrian pada WorkerPool memastikan bahwa jumlah tugas yang berjalan secara bersamaan tidak melebihi jumlah worker yang tersedia.

Jangan Campur Cluster dengan Worker Threads Secara Sembarangan

Menjalankan worker threads di dalam proses yang sudah di-cluster dapat menyebabkan jumlah thread meledak secara eksponensial. Jika sebuah server memiliki 8 inti CPU dengan 8 proses cluster, dan setiap proses membuat pool berisi 8 worker thread, total thread yang aktif menjadi 64 -- jauh melebihi kapasitas optimal. Gunakan clustering untuk mendistribusikan koneksi HTTP dan worker threads untuk tugas CPU-intensive spesifik, dengan jumlah thread per worker yang dibatasi (biasanya 2-4 per proses cluster).

Optimasi Memori dan Tekanan Garbage Collector

Garbage collector (GC) V8 bekerja dalam dua generasi: young generation untuk objek berumur pendek dan old generation untuk objek yang bertahan melewati beberapa siklus GC. Tekanan GC yang tinggi -- ditandai dengan alokasi objek baru secara masif dalam loop yang padat -- menyebabkan jeda yang mengganggu responsivitas aplikasi.

Strategi utama untuk mengurangi tekanan GC meliputi penggunaan kembali buffer, minimalisasi alokasi objek dalam hot path, dan konfigurasi parameter V8 yang sesuai dengan profil beban kerja:

memory-optimization.jsjavascript
// Patterns that reduce GC pressure

// ANTI-PATTERN: Creating objects in hot loops
function processItemsBad(items) {
  return items.map(item => ({
    id: item.id,
    name: item.name.trim(),
    score: calculateScore(item),  // New object per iteration
    metadata: { processed: true, timestamp: Date.now() }
  }));
}

// OPTIMIZED: Reuse buffers and minimize allocations
const reusableBuffer = Buffer.alloc(4096);

function processItemsGood(items, output) {
  // Reuse the output array instead of creating new one
  output.length = 0;
  for (let i = 0; i < items.length; i++) {
    // Mutate in place when safe to do so
    output.push(items[i].id);
  }
  return output;
}

// Monitor heap usage for leak detection
function checkMemory() {
  const used = process.memoryUsage();
  return {
    heapUsedMB: Math.round(used.heapUsed / 1024 / 1024),
    heapTotalMB: Math.round(used.heapTotal / 1024 / 1024),
    externalMB: Math.round(used.external / 1024 / 1024),
    rsssMB: Math.round(used.rss / 1024 / 1024),
  };
}

// V8 flags for production GC tuning
// node --max-old-space-size=4096 --max-semi-space-size=128 app.js
// --max-old-space-size: Set old generation limit (default ~1.7GB)
// --max-semi-space-size: Increase young generation (default 16MB)

Flag --max-old-space-size menentukan batas memori old generation. Untuk aplikasi yang menangani dataset besar, meningkatkan nilai ini dari default 1.7GB ke 4GB atau lebih dapat mencegah crash akibat out-of-memory. Sementara itu, --max-semi-space-size mengontrol ukuran young generation -- memperbesar nilainya mengurangi frekuensi minor GC pada aplikasi dengan alokasi objek yang sangat tinggi.

Pemantauan heap secara berkala menggunakan process.memoryUsage() memungkinkan deteksi dini memory leak. Tren peningkatan heap yang konsisten tanpa penurunan merupakan indikator kuat adanya kebocoran memori yang memerlukan investigasi lebih lanjut.

Monitoring Produksi dengan OpenTelemetry

OpenTelemetry telah menjadi standar de facto untuk observability di ekosistem Node.js. Dengan instrumentasi otomatis, setiap permintaan HTTP, query database, dan panggilan DNS dapat dilacak tanpa perubahan kode aplikasi. Metrik event loop lag yang digabungkan dengan tracing memberikan visibilitas menyeluruh terhadap performa sistem.

otel-setup.jsjavascript
// OpenTelemetry setup for Node.js performance monitoring

const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');

const sdk = new NodeSDK({
  metricReader: new PrometheusExporter({ port: 9464 }),
  instrumentations: [
    getNodeAutoInstrumentations({
      // Instrument HTTP, Express, DNS, fs, and more
      '@opentelemetry/instrumentation-fs': { enabled: false }, // Too noisy
    }),
  ],
});

sdk.start();

// Custom event loop lag metric
const { metrics } = require('@opentelemetry/api');
const meter = metrics.getMeter('app');

const eventLoopLag = meter.createHistogram('nodejs.event_loop.lag', {
  description: 'Event loop lag in milliseconds',
  unit: 'ms',
});

// Report event loop lag every second
const { monitorEventLoopDelay } = require('perf_hooks');
const h = monitorEventLoopDelay({ resolution: 10 });
h.enable();

setInterval(() => {
  eventLoopLag.record(h.percentile(99) / 1e6);
  h.reset();
}, 1000);

Konfigurasi di atas mengekspos metrik dalam format Prometheus pada port 9464, yang dapat di-scrape oleh Prometheus dan divisualisasikan melalui Grafana. Instrumentasi otomatis menangkap metrik HTTP (latensi, throughput, error rate), sementara metrik kustom event loop lag memberikan insight tambahan yang spesifik untuk Node.js.

Dalam arsitektur mikroservis, distributed tracing yang disediakan OpenTelemetry memungkinkan pelacakan sebuah permintaan dari awal hingga akhir melewati berbagai layanan. Kemampuan ini sangat berharga untuk mengidentifikasi bottleneck yang terjadi pada interaksi antar-layanan.

Matriks Keputusan: Memilih Strategi yang Tepat

Memilih antara clustering, worker threads, atau pendekatan lainnya bergantung pada karakteristik beban kerja. Tabel berikut menyajikan panduan keputusan berdasarkan skenario yang umum ditemui:

| Skenario | Strategi | Alasan | |---|---|---| | API server dengan beban tinggi | Clustering (N proses) | Mendistribusikan koneksi HTTP ke seluruh inti CPU | | Pemrosesan gambar/video | Worker threads | Mengisolasi tugas CPU-intensive dari thread utama | | Parsing JSON berukuran besar | Streaming parser | Mencegah blocking event loop tanpa overhead thread | | Operasi kriptografi | API async bawaan | Sudah menggunakan thread pool libuv secara internal | | Kompresi data real-time | Worker threads | Memparalelkan kompresi tanpa memblokir respons HTTP | | Microservice I/O-intensive | Clustering + async I/O | Memaksimalkan throughput I/O di seluruh inti CPU | | Batch processing berkala | Worker threads + antrian | Memproses batch secara paralel tanpa mengganggu server utama |

Secara umum, clustering adalah pilihan pertama untuk meningkatkan throughput HTTP, sementara worker threads lebih tepat untuk tugas komputasi spesifik yang berdurasi panjang. Keduanya dapat dikombinasikan dengan batasan yang jelas pada jumlah total thread.

Peningkatan di Node.js 24 LTS

Node.js 24 LTS yang dirilis tahun 2026 menghadirkan beberapa peningkatan performa yang signifikan. V8 engine versi terbaru memberikan peningkatan throughput garbage collector hingga 15% untuk beban kerja umum. Diagnostics channel yang telah distabilkan memungkinkan monitoring non-invasif tanpa overhead tambahan. Permission Model yang telah keluar dari status eksperimental memberikan lapisan keamanan tambahan tanpa dampak performa yang berarti. Selain itu, perbaikan pada HTTP parser dan peningkatan efisiensi fetch API menjadikan Node.js 24 pilihan yang sangat kuat untuk layanan produksi baru.

Checklist Praktis Optimasi Performa Node.js

Berikut adalah daftar periksa yang dapat digunakan sebagai panduan saat mengoptimalkan aplikasi Node.js untuk lingkungan produksi:

Event Loop

  • Identifikasi dan eliminasi semua operasi sinkron pada jalur permintaan (request path)
  • Implementasikan monitoring ELU dengan ambang batas alert pada 70%
  • Gunakan streaming parser untuk payload JSON di atas 1MB
  • Selalu gunakan varian asinkron untuk operasi kriptografi

Clustering dan Worker Threads

  • Aktifkan clustering dengan jumlah worker sesuai inti CPU yang tersedia
  • Implementasikan graceful shutdown pada proses primary dan setiap worker
  • Gunakan worker threads untuk tugas CPU-intensive dengan durasi di atas 10ms
  • Batasi total thread (cluster workers x thread pool) agar tidak melebihi 2x jumlah inti CPU

Memori dan GC

  • Konfigurasikan --max-old-space-size sesuai ketersediaan RAM server
  • Minimalkan alokasi objek dalam hot loop -- gunakan kembali buffer dan array
  • Pantau tren heap secara berkala untuk deteksi dini memory leak
  • Pertimbangkan --max-semi-space-size untuk aplikasi dengan alokasi tinggi

Monitoring dan Observability

  • Integrasikan OpenTelemetry dengan instrumentasi otomatis
  • Ekspos metrik event loop lag, ELU, heap usage, dan HTTP latency
  • Konfigurasikan alert untuk p99 latency, error rate, dan ELU
  • Terapkan distributed tracing untuk arsitektur mikroservis

Mulai berlatih!

Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

Kesimpulan

Performa Node.js bukan sekadar tentang menulis kode yang cepat -- melainkan tentang memahami mekanisme internal runtime dan menerapkan strategi yang tepat untuk setiap jenis beban kerja. Event loop yang dipahami dengan baik memungkinkan pencegahan blocking sebelum terjadi. Clustering memanfaatkan kapasitas penuh hardware server. Worker threads mengisolasi komputasi berat tanpa mengorbankan responsivitas. Dan monitoring yang komprehensif memberikan visibilitas untuk mengidentifikasi serta menyelesaikan masalah performa sebelum berdampak pada pengguna.

Untuk memperdalam pemahaman tentang topik-topik ini, tersedia beberapa sumber belajar yang relevan. Track teknologi Node.js & NestJS menyediakan jalur pembelajaran terstruktur yang mencakup seluruh aspek pengembangan backend dengan Node.js. Modul middleware and interceptors membahas pola-pola arsitektural yang sering muncul dalam wawancara teknis. Selain itu, panduan pertanyaan wawancara backend Node.js memberikan gambaran komprehensif tentang materi yang diuji dalam sesi wawancara untuk posisi backend engineer.

Tag

#node.js
#performance
#event-loop
#clustering
#optimization
#worker-threads

Bagikan

Artikel terkait