Webhook masuk, agent jalan, lalu model memutuskan butuh empat tool call. Sembilan puluh detik kemudian workflow baru selesai. Di instalasi n8n default, proses yang sama juga melayani editor, API, dan semua trigger lain yang kamu punya. Buka tab kedua, UI-nya macet menunggu.
Queue mode memisahkan dua pekerjaan itu. Satu proses menerima webhook dan timer, worker mengambil eksekusi dari antrean Redis dan menjalankannya, Postgres menyimpan state yang dibutuhkan keduanya. Tambah worker kedua nanti, throughput naik tanpa mengubah workflow.
Yang saya tulis di bawah ini adalah setup yang akan saya pakai hari ini: n8n 2.45.7, Postgres 18, Redis, satu worker, plus sidecar task runner. Setelah itu workflow AI Agent yang memanggil tool dari MCP server eksternal, lalu kebalikannya: Claude Desktop memanggil workflow n8n sebagai tool MCP.
Yang perlu disiapkan
- Docker Engine dengan Compose v2. Cek pakai
docker compose version. - Host minimal 4 GB RAM dan 2 vCPU. Tiap proses n8n punya sidecar task runner sendiri, jadi hitung juga kebutuhan itu.
- API key LLM untuk bagian agent.
- Domain dan TLS kalau webhook atau endpoint MCP harus bisa diakses dari luar.
Langkah 1: bikin secret dulu
mkdir -p ~/n8n && cd ~/n8n
openssl rand -hex 32 # N8N_ENCRYPTION_KEY
openssl rand -hex 24 # N8N_RUNNERS_AUTH_TOKEN
Isi .env:
N8N_VERSION=2.45.7
POSTGRES_USER=n8n
POSTGRES_PASSWORD=ganti-ini
POSTGRES_DB=n8n
N8N_ENCRYPTION_KEY=ganti-dengan-64-karakter-hex
N8N_RUNNERS_AUTH_TOKEN=ganti-dengan-48-karakter-hex
N8N_WEBHOOK_URL=https://n8n.example.com
TZ=Asia/Jakarta
Encryption key sering dianggap remeh. Saat boot pertama n8n membuat satu key dan menyimpannya di /home/node/.n8n. Semua worker dan proses webhook harus memakai key yang sama persis, kalau tidak, credential yang dipakai node tidak bisa didekripsi. Set eksplisit dari awal, simpan di secret manager, dan anggap hilang berarti harus input ulang semua credential.
Langkah 2: compose.yml
x-n8n-env: &n8n-env
DB_TYPE: postgresdb
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: "5432"
DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
DB_POSTGRESDB_USER: ${POSTGRES_USER}
DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
EXECUTIONS_MODE: queue
QUEUE_BULL_REDIS_HOST: redis
QUEUE_BULL_REDIS_PORT: "6379"
N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
N8N_WEBHOOK_URL: ${N8N_WEBHOOK_URL}
GENERIC_TIMEZONE: ${TZ}
TZ: ${TZ}
N8N_RUNNERS_MODE: external
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
N8N_RUNNERS_BROKER_LISTEN_ADDRESS: 0.0.0.0
services:
postgres:
image: postgres:18
restart: always
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
PGDATA: /var/lib/postgresql/data
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
retries: 10
redis:
image: redis:7-alpine
restart: always
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
retries: 10
n8n-main:
image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
restart: always
ports:
- "5678:5678"
environment:
<<: *n8n-env
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
n8n-main-runner:
image: n8nio/runners:${N8N_VERSION}
restart: always
environment:
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
N8N_RUNNERS_TASK_BROKER_URI: http://n8n-main:5679
depends_on:
- n8n-main
n8n-worker:
image: docker.n8n.io/n8nio/n8n:${N8N_VERSION}
restart: always
command: ["worker", "--concurrency=10"]
environment:
<<: *n8n-env
QUEUE_HEALTH_CHECK_ACTIVE: "true"
volumes:
- n8n_data:/home/node/.n8n
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
n8n-worker-runner:
image: n8nio/runners:${N8N_VERSION}
restart: always
environment:
N8N_RUNNERS_AUTH_TOKEN: ${N8N_RUNNERS_AUTH_TOKEN}
N8N_RUNNERS_TASK_BROKER_URI: http://n8n-worker:5679
depends_on:
- n8n-worker
volumes:
db_data:
redis_data:
n8n_data:
Ada tiga detail di file itu yang gampang salah.
PGDATA di Postgres 18. Image resminya memindahkan direktori data default di v18. Tanpa variabel ini, volume tidak menutupi lokasi tulis Postgres yang sebenarnya, dan database terlihat kosong setiap kali container restart.
Sidecar runner per proses. Di mode external, image n8nio/runners berisi task runner JS dan Python, dan tiap proses n8n butuh sidecar sendiri. Queue mode dengan satu worker berarti dua sidecar: satu untuk main, satu untuk worker. Ini lapisan isolasi antara kode dari node Code dan sisa sistem, jadi container tambahannya sepadan.
Volume n8n_data dipakai bersama. Kedua proses mount volume yang sama karena keduanya perlu encryption key dan config instance. Workflow dan eksekusi ada di database, sedangkan key ada di volume.
Langkah 3: nyalakan dan buktikan
docker compose up -d
docker compose ps
curl -sf localhost:5678/healthz && echo " main ok"
docker compose logs -f n8n-worker
Buka http://localhost:5678, buat akun owner, lalu masuk ke Settings dan pilih Workers. Worker kamu harus muncul lengkap dengan concurrency dan jumlah job yang sedang jalan. Kalau daftarnya kosong, worker gagal konek ke Redis atau start dengan encryption key berbeda dari main. Dua kegagalan itu tampil sama di UI, jadi cek docker compose logs n8n-worker dulu sebelum mulai mengubah env sana-sini.
Worker hanya membuka /healthz dan /healthz/readiness kalau QUEUE_HEALTH_CHECK_ACTIVE=true. Kalau load balancer perlu probe, publish port-nya dan arahkan health check ke situ.
Langkah 4: agent yang memanggil MCP server eksternal
Bikin workflow dengan Webhook trigger dan node AI Agent. Pasang dua sub-node: chat model (OpenAI Chat Model, Anthropic Chat Model, mana yang key-nya ada) dan MCP Client Tool.
Di node MCP Client Tool:
- SSE Endpoint: URL MCP server, misalnya
https://mcp.example.com/sse. - Authentication: None, Bearer, Header, Multiple Headers, atau OAuth2. Pakai Bearer dan tempel token untuk server yang tidak sepenuhnya kamu percaya.
- Tools to Include: All, Selected, atau All Except.
Pilih Selected dan daftarkan hanya tool yang dibutuhkan agent. Setiap tool yang diekspos dideskripsikan ke context model di tiap turn, jadi server dengan empat puluh tool membakar token untuk deskripsi dan bikin pemilihan tool lebih buruk. Filter di node jauh lebih murah daripada memperbaikinya lewat prompt.
Lalu batasi perilakunya di system message:
You are an operations assistant. Use the MCP tools for anything factual.
Rules:
1. Never guess a value a tool can return.
2. If a tool fails twice, stop and report the error text verbatim.
3. Answer in at most five sentences unless asked for detail.
Satu catatan versi: setting agent type di node AI Agent sudah deprecated sejak n8n 1.82.0, dan semua node AI Agent sekarang berjalan sebagai Tools Agent. Versi 1 node itu dihapus di n8n 3.0, jadi upgrade node lama sebelum migrasi. Kalau ada tutorial yang menyuruh memilih "SQL Agent" atau "Conversational Agent", tutorialnya lebih tua dari perubahan itu. Pakai tool sub-node database dengan Agent node versi sekarang.
Langkah 5: jadikan n8n sebagai MCP server
Ini arah yang sering terlewat. Taruh MCP Server Trigger di workflow kosong, sambungkan Custom n8n Workflow Tool ke workflow yang mau diekspos, dan set authentication ke Bearer. n8n memberi dua URL: test URL yang menampilkan data ke editor saat kamu membangun, dan production URL yang aktif setelah workflow di-publish.
n8n tidak mendukung stdio, hanya SSE dan streamable HTTP. Untuk Claude Desktop, jembatani pakai mcp-remote:
{
"mcpServers": {
"n8n": {
"command": "npx",
"args": [
"mcp-remote",
"https://n8n.example.com/mcp/your-path",
"--header",
"Authorization: Bearer ${AUTH_TOKEN}"
],
"env": {
"AUTH_TOKEN": "your-bearer-token"
}
}
}
}
Kalau ada nginx di depan, location MCP harus mematikan buffering. SSE mempertahankan koneksi tetap terbuka, dan proxy yang buffering akan menahan event sampai response selesai, yang artinya tidak pernah.
location /mcp/ {
proxy_http_version 1.1;
proxy_buffering off;
gzip off;
chunked_transfer_encoding off;
proxy_set_header Connection '';
}
Bagian yang bikin queue mode bermasalah
- SQLite tidak didukung di queue mode. Pakai Postgres atau MySQL, tanpa pengecualian.
- Response webhook dikirim dari worker ke main lewat pesan Redis, dibatasi 64 MiB lewat
N8N_WEBHOOK_RESPONSE_RELAY_SIZE_MAX. Batas yang sama berlaku untuk hasil tool dari workflow MCP Trigger, dan hasil tool tidak bisa di-offload. N8N_WEBHOOK_URLmenggantikanWEBHOOK_URLmulai n8n 2.30.0. Versi lama mengabaikan nama baru.- n8n 2.0 menghapus
QUEUE_WORKER_MAX_STALLED_COUNTdan membuatN8N_RUNNERS_ENABLEDtidak lagi perlu. - Kalau ada beberapa webhook replica, arahkan semua request
/mcp*ke satu replica khusus. Koneksi persisten dan round-robin tidak cocok. - Concurrency default 10 per worker. Nilai sangat kecil yang disebar ke banyak worker menghabiskan connection pool Postgres, dan gejalanya berupa delay acak, bukan error yang jelas.
Kapan pakai ini, kapan pilih yang lain
Pakai n8n kalau pekerjaannya didominasi integrasi plus beberapa langkah AI, dan orang yang tidak menulis kode perlu ikut mengedit workflow. Di situ kekuatannya, dan queue mode membuatnya tahan beban.
Pakai Dify atau Flowise kalau produknya aplikasi chat atau RAG, dan UI-nya memang seharusnya soal prompt, knowledge base, dan setting model, bukan node HTTP.
Pakai Temporal atau LangGraph kalau workflow-nya logika bisnis inti yang harus masuk version control, punya test, lewat code review, dan tidak butuh editor visual. Kamu tukar library node dengan kontrol penuh.
Soal lisensi: kode n8n source-available di bawah Sustainable Use License, dan n8n sendiri tidak menyebutnya open source karena lisensinya membatasi penggunaan komersial. Pemakaian internal bisnis gratis. White-label, menjual ulang sebagai produk otomasi, atau membiarkan pelanggan membangun workflow lewat UI kamu, tidak.
Kalau cuma ingat satu hal
Masalah di n8n self-hosted jarang ada di workflow-nya. Biasanya di satu proses yang mencoba melayani editor, menahan koneksi webhook, dan menjalankan rantai agent panjang sekaligus. Pisahkan eksekusi ke worker, bagikan encryption key dengan benar, dan jalankan sidecar runner di mode external. Editor tetap responsif dan tool call yang lama berhenti jadi masalah orang lain.
Referensi
- Node MCP Client Tool, dokumentasi n8n: https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolmcp
- Enable queue mode (worker, Redis, webhook processor, concurrency): https://docs.n8n.io/deploy/host-n8n/configure-n8n/scaling/enable-queue-mode
- Node MCP Server Trigger, termasuk blok nginx dan catatan replica: https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-langchain.mcptrigger
- FAQ lisensi n8n (Sustainable Use License, fair-code): https://docs.n8n.io/n8n-community-license