Belajar n8n - Performance Optimization
Series/Belajar n8n/Episode 16
Episode 16 of 23

Belajar n8n - Performance Optimization

Optimalkan performa n8n: memecah workflow besar menjadi sub-workflow yang reusable, menerapkan batch processing dan concurrency, mengatur resource serta runtime node, sampai meningkatkan throughput dengan queue mode dan worker scaling.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Di episode 15 kalian men-deploy n8n secara produksi dengan Docker Compose, Kubernetes, dan queue mode. Sekarang instance-nya sehat — tapi workflow mulai terasa lambat. Satu workflow "laporan raksasa" memproses ribuan baris dalam satu kali jalan, beberapa workflow memuat logika yang sama, dan eksekusi saling berebut CPU di main.

Episode 16 membahas Performance Optimization: memecah workflow besar menjadi sub-workflow yang bisa dipakai ulang, menerapkan batch processing dan concurrency, serta mengoptimalkan execution runtime dan throughput.

Ukur Dulu, Baru Optimasi

Aturan pertama optimasi: jangan menebak. Sebelum mengubah apa pun, lihat data yang sudah kalian kumpulkan dari episode 13:

  • Durasi per node di Execution History — node mana yang menghabiskan sebagian besar waktu?
  • Metrik Prometheus — pola eksekusi per jam, antrean Redis yang menumpuk, metrik Node.js seperti memori.
  • Pola data — berapa banyak item yang melewati tiap node, dan seberapa sering trigger memicu eksekusi.

Optimasi yang tidak berbasis pengukuran biasanya memperbaiki hal yang salah. Ukur, temukan bottleneck, perbaiki, lalu ukur lagi.

Memecah Workflow Menjadi Sub-workflow

Workflow yang menumpuk semua logika dalam satu kanvas sulit dipahami dan sulit dijalankan cepat. Solusinya adalah memecahnya menjadi sub-workflow yang dijalankan lewat node Execute Sub-workflow. Setiap sub-workflow punya satu tanggung jawab — normalisasi data, panggilan API, formatting laporan — dan bisa dipanggil dari banyak workflow induk.

Perbedaan performa terbesar ada pada mode eksekusinya:

Dua mode Execute Sub-workflow
Run once for each item -> sub-workflow dieksekusi N kali
Run once for all items -> sub-workflow dieksekusi 1 kali, N item sekaligus

Memilih "each item" untuk 5.000 item berarti menjalankan sub-workflow 5.000 kali — setiap kali dengan overhead load, credential, dan sambungan. Pilih "all items" ketika sub-workflow memproses data secara batch, dan gunakan mode per item hanya bila setiap item memang butuh konteks eksekusi terpisah. Sub-workflow yang reusable juga membuat perbaikan menyebar: ubah sekali, semua workflow induk ikut membaik. Saat dijalankan dalam queue mode, sub-workflow yang di-fan-out dari satu trigger bahkan bisa dieksekusi paralel di beberapa worker sekaligus.

Aturan pemecahan yang mudah diingat: bila sebuah blok node muncul di lebih dari dua workflow, atau sebuah workflow mulai sulit dibaca karena terlalu panjang, saat itulah blok itu layak dipindahkan ke sub-workflow.

Batch Processing & Loop Patterns

Ketika workflow harus memproses ribuan baris, memproses satu per satu terlalu lambat; memproses semuanya sekaligus bisa membuat memori jebol. Jalan tengahnya adalah batch processing dengan node SplitInBatches — data dipecah menjadi kelompok berukuran tetap, lalu tiap batch diproses dalam iterasi loop:

Pola batch dengan SplitInBatches
Input 10.000 item
  -> SplitInBatches (batchSize: 500)
  -> Loop node (proses batch)
  -> jika masih ada sisa, ulangi dari awal

Ukuran batch adalah kompromi: terlalu kecil berarti banyak iterasi dan overhead per siklus; terlalu besar berarti lonjakan memori per batch. Mulai dari beberapa ratus item per batch, lalu sesuaikan berdasarkan beban API tujuan dan batas memori instance. Pola ini sekaligus melindungi service eksternal dari ledakan request — terutama penting saat berintegrasi dengan API pihak ketiga yang membatasi rate.

Satu kesalahan yang sering terjadi: menaruh SplitInBatches di dalam alur yang sudah berjalan per item, sehingga batch tidak pernah terpakai. SplitInBatches bekerja paling baik di titik awal pipeline — pecahkan sejak awal, dan biarkan setiap iterasi mengolah satu batch dari awal sampai akhir.

Concurrency & Resource Tuning

Selain struktur workflow, tuning lingkungan menentukan berapa banyak eksekusi yang bisa berjalan bersamaan. Di main, batasnya dikendalikan variabel lingkungan:

Batasi eksekusi bersamaan di main
N8N_CONCURRENCY_PRODUCTION_LIMIT=10
N8N_CONCURRENCY_POLLING_LIMIT=5

Nilai -1 berarti tanpa batas (default). Mengatur batas yang masuk akal mencegah satu pekerjaan berat membanjiri instance. Di queue mode, concurrency berlaku per worker — kelola lewat flag --concurrency pada n8n worker atau N8N_CONCURRENCY_PRODUCTION_LIMIT di environment worker, sebagaimana dibahas di episode 15.

Resource Node.js juga bisa diatur. Heap memory dibatasi nilai default yang mungkin terlalu kecil untuk workflow dengan banyak data:

Perbesar heap memory Node.js
NODE_OPTIONS=--max-old-space-size=2048

Sesuaikan dengan memori fisik yang dialokasikan ke container, dan seimbangkan dengan batas CPU pada compose/values Helm agar proses tidak di-throttle.

Info

Untuk Code node yang berat, perhatikan eksekusi di task runners: n8n versi terbaru menjalankan kode di proses terpisah sehingga workload JavaScript tidak membebani event loop utama. Pastikan memori yang dialokasikan cukup, karena kode sekarang berjalan di luar proses n8n itu sendiri.

Mengoptimalkan Execution Runtime

Waktu eksekusi paling sering hilang di panggilan jaringan. Pola pemborosan yang umum:

  • N+1 calls — memanggil API satu kali per item padahal API mendukung batch. Gunakan operasi bulk dari node, atau kumpulkan ID lalu panggil sekali.
  • Loop tak perlu — proses batch di dalam Code node daripada Loop jika logikanya murni transformasi.
  • HTTP Request berulang — data yang jarang berubah (misalnya metadata produk) bisa di-cache di Redis daripada diambil tiap eksekusi.
  • Data mati ikut mengalir — sebelum Convert to File atau pengiriman, buang kolom yang tidak terpakai dengan Set atau Remove Duplicates untuk memangkas payload antar node.

Pemangkasan data juga berlaku pada database: kebijakan prune dari episode 13 (EXECUTIONS_DATA_PRUNE dan EXECUTIONS_DATA_MAX_AGE) menjaga tabel eksekusi tidak membengkak, sehingga query riwayat tetap cepat. Runtime yang sehat dimulai dari data yang tidak menganggur di mana-mana.

Pola yang juga patut diperhatikan adalah trigger yang terlalu rajin. Cron yang berjalan setiap menit untuk memeriksa data yang berubah tiap jam membuang banyak slot eksekusi — perbesar interval, atau manfaatkan trigger polling yang menyertakan kondisi berhenti lebih awal (misalnya langsung berhenti ketika tidak ada data baru). Eksekusi yang tidak pernah dimulai adalah eksekusi yang paling cepat.

Throughput dengan Queue Mode

Ketika satu proses tidak lagi sanggup mengeksekusi semua workload, throughput dinaikkan secara horizontal. Queue mode dari episode 15 memindahkan eksekusi ke worker: main hanya menyalurkan job ke Redis, dan sekumpulan worker mengonsumsinya. Tambah throughput dengan menambah replica worker — bukan dengan memperbesar satu instance.

Beberapa knob yang menyesuaikan perilaku:

  • OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true — eksekusi manual dari editor juga dialihkan ke worker, menjaga main tetap ringan untuk UI.
  • Scaling worker saat peak — pertambahan worker menaikkan kapasitas paralel; antrean Redis menyalurkan job ke worker yang menganggur.
  • Batch pekerjaan — gabungkan banyak item kecil menjadi satu eksekusi batch di worker, kurangi overhead per job.

Throughput bukan hanya soal menambah worker, tetapi memastikan setiap worker mengerjakan job yang tepat dengan data yang sudah dipangkas — kombinasi struktur workflow dari bab-bab sebelumnya dengan scaling dari episode 15.

Penutup

Episode 16 menuntun kalian dari workflow yang lambat menjadi sistem yang terukur. Kalian mengukur dulu sebelum mengoptimasi, memecah workflow raksasa menjadi sub-workflow reusable, menerapkan batch processing dengan SplitInBatches, mengatur concurrency dan resource Node.js, memangkas pemborosan runtime, dan menaikkan throughput lewat queue mode dan worker scaling.

Inti yang harus dibawa pulang:

  • Ukur dulu — optimasi berbasis durasi per node dan metrik, bukan tebakan.
  • Sub-workflow "all items" memangkas ribuan eksekusi menjadi satu eksekusi batch.
  • SplitInBatches menyeimbangkan kecepatan dan konsumsi memori untuk data besar.
  • Concurrency diatur eksplisit dengan N8N_CONCURRENCY_PRODUCTION_LIMIT dan flag worker.
  • Throughput didapat dari worker scaling, bukan membesarkan satu instance.

Di episode 17 berikutnya kita memperluas n8n melampaui node bawaan: Extensions & Custom Nodes — membuat custom node dan mengemasnya sendiri, memakai community nodes, serta plugin development untuk automation yang lebih kaya. Sampai jumpa!

Belajar n8n - Performance Optimization | Belajar n8n