n8n queue mode 2026: self-hosted AI-työnkulut tuotannossa Postgres+Redis-pinolla

n8n queue mode on ainoa realistinen tapa ajaa AI-työnkulkuja tuotannossa. Käytännön opas Postgres+Redis-pinon rakentamiseen, AI Agent -noden asetuksiin ja workereiden skaalaukseen Docker Composessa ja Kubernetesissa.

Päivitetty: 23. elokuuta 2026

n8n queue mode on n8n:n hajautettu suoritustila, jossa pääprosessi vain vastaanottaa työn ja siirtää sen Redis-jonoon, josta erilliset worker-kontit suorittavat sen taustalla. Se on käytännössä ainoa realistinen tapa ajaa AI-työnkulkuja tuotannossa, koska yksittäinen LLM-kutsu voi kestää minuutteja ja tukkia oletusarkkitehtuurin webhook-vastaanoton. Olen viimeisen kolmen vuoden aikana migratoinut kymmeniä self-hosted n8n -asennuksia queue modeen, ja tässä oppaassa käyn läpi tarkalleen sen komponentit, Docker Compose -tuotantopinon, AI Agent -noden asetukset ja ne sudenkuopat, joihin melkein kaikki kompastuvat ensimmäisellä kerralla.

  • Queue mode vaatii PostgreSQL 14+ ja Redis 6.0+; SQLite ei toimi ja kaikilla prosesseilla on oltava sama N8N_ENCRYPTION_KEY.
  • Yksi worker-kontti käsittelee oletuksena kymmenen samanaikaista suoritusta; AI-työnkuluille laske 2–4 workeria per käytettävissä oleva vCPU.
  • Erillinen webhook-vastaanottaja (webhook processor) estää LLM-suoritusten hidastamasta 200 ms:n vastausvaatimuksia esimerkiksi WhatsApp- tai Stripe-webhookeille.
  • AI Agent -node on cluster node, joka pyörii työntekijässä, ja Chat Model-, Memory- sekä Tool-alinodet perivät saman suoritusympäristön ja aikakatkaisun.
  • N8N_GRACEFUL_SHUTDOWN_TIMEOUT ja EXECUTIONS_TIMEOUT määrittävät, kuinka autoskaalaus käyttäytyy Kubernetesin SIGTERM-signaalin jälkeen.
  • GDPR-vaatimusten mukainen retention hoidetaan EXECUTIONS_DATA_PRUNE-asetuksilla ja Postgresin partitiotauluilla, kun execution_entity ylittää 20 miljoonaa riviä.

Mikä on n8n queue mode ja miksi AI-työnkulut vaativat sen?

Queue mode on n8n:n vaihtoehtoinen suoritustila, jossa työnkulkujen ajo irrotetaan editori- ja webhook-liikenteestä. Oletuksena (regular mode) sama Node.js-prosessi tarjoilee editorin, ottaa vastaan webhookit ja suorittaa ne. Riittää hyvin silloin, kun ajaa muutamaa Slack-notifikaatiota päivässä, mutta romahtaa täysin siinä vaiheessa, kun yksi LLM-kutsu Claude Sonnetiin kestää 40 sekuntia ja niitä tulee sata rinnakkain.

Berliinin fintechillä, jossa olin viisi vuotta, saimme oletusarkkitehtuurin polvilleen noin 8 000 suorituksella päivässä. Editori jäätyi joka päivä klo 9:15, kun Salesforce sync -workflow ajastui, ja Ops-tiimin oli mahdotonta debugata muita työnkulkuja samaan aikaan. Queue moden käyttöönotto vei kaksi viikkoa, mutta poisti ongelman kokonaan (ja avasi tien AI Agent -pohjaisten työnkulkujen ottamiseen, koska LLM-kutsujen vaihteleva kesto ei enää tukkinut mitään).

Käytännön sääntönä: heti kun sinulla on yksikin työnkulku, joka odottaa ulkoista API-vastausta yli 10 sekuntia, olet queue mode -asiakas. AI Agent -noden kohdalla tämä pätee aina. Jopa yksinkertainen ReAct-agentti tekee tyypillisesti 3–7 LLM-kutsua, mikä tarkoittaa 15–90 sekunnin suoritusaikoja. Regular modessa nämä tukkivat webhook-endpointin, mikä johtaa 502-virheisiin lähdejärjestelmässä.

Queue mode -arkkitehtuurin komponentit

Queue mode jakaa n8n:n kolmeen loogiseen rooliin, jotka kaikki ajavat samaa n8n Docker -imagea mutta eri komennoilla ja ympäristömuuttujilla:

  • Main-prosessi tarjoilee editori-UI:n, REST-API:n ja hallinnoi triggeriä (cron, poll). Ei suorita työnkulkuja itse.
  • Webhook processor (valinnainen erillinen kontti) ottaa vastaan HTTP-webhook-kutsut ja työntää suoritukset Redis-jonoon. Jos erillistä webhook processoria ei ole, main hoitaa tämän.
  • Worker-prosessit pollaavat Redisistä työtä ja suorittavat sen. Näitä skaalataan horisontaalisesti, tyypillisesti 3–20 replicaa.

Redis toimii viestinvälittäjänä (Bull-pohjainen jonokirjasto). PostgreSQL säilöö sekä työnkulkujen määritelmät että suoritusten historian (execution_entity-taulu). Kaikki komponentit lukevat ja kirjoittavat samaan Postgresiin, joten sen kapasiteetti on lähes aina ensimmäinen pullonkaula.

Tärkeä yksityiskohta, joka jää monelta huomaamatta: workereilla ei ole pääsyä ulkopuolelta. Ne eivät kuuntele portteja (paitsi valinnaista terveystarkistusporttia 5679), eivätkä ne näy load balancerissa. Vain main ja webhook processorit tarvitsevat julkiset endpointit. Tämä yksinkertaistaa turvallisuusryhmiä merkittävästi verrattuna vaikkapa LangGraph- tai CrewAI-pohjaisiin moniagenttijärjestelmiin, joissa jokainen agentti tyypillisesti tarvitsee oman verkkokerroksen.

PostgreSQL-, Redis- ja salausvaatimukset

Ennen kuin edes ajattelet queue moden käyttöönottoa, varmista nämä kolme asiaa. Ne eivät ole neuvoteltavissa.

PostgreSQL 14 tai uudempi

SQLite ei toimi queue modessa, ja se on hyvä asia. 500 000 rivin execution_entity-taulussa SQLite-lukituskonteksti tulee vastaan päivässä. Käytä käytännössä Postgres 15:tä tai 16:ta. Aseta shared_buffers = 25 % RAMista, effective_cache_size = 75 % ja max_connections vähintään (workereiden määrä × 10) + 30. Yleinen virhe on jättää max_connections oletukseen 100, jolloin kymmenen workeria concurrencyllä 10 kuluttaa koko poolin ja main saa "sorry, too many clients already" -virheitä.

Redis 6.0 tai uudempi

Bull-jonokirjasto käyttää Redisin BLPOP- ja Lua-skriptejä; Redis 6.0 on minimi. Aseta maxmemory-policy = noeviction. Jos Redis alkaa poistaa avaimia satunnaisesti muistin loppuessa, häviät työtehtäviä hiljaisesti. Suosittelen Redis Sentineliä tai Redis Cluster -pohjaista pystytystä tuotannossa; yhden solmun Redis on yksittäinen vikapiste koko järjestelmälle.

Yhtenäinen N8N_ENCRYPTION_KEY

Kaikilla prosesseilla (main, webhook processorit ja jokainen worker) on oltava tarkalleen sama salausavain. Se salaa credentials-tietueet Postgresissä. Jos worker käynnistyy väärällä avaimella, kaikki työnkulut, jotka käyttävät tunnisteita, kaatuvat "credentials could not be decrypted" -virheeseen. Generoi avain kerran (openssl rand -hex 32) ja levitä se secrets managerin kautta. Älä koskaan luo sitä satunnaisesti käynnistyksen yhteydessä.

Docker Compose -tuotantopino askel askeleelta

Tämä on minimaalinen mutta tuotantoon kelpaava Docker Compose -pino. Käytin sitä pohjana kolmessa asiakkaani migraatiossa viimeisen kuuden kuukauden aikana.

version: "3.9"

x-shared: &shared
  image: docker.n8n.io/n8nio/n8n:1.72.0
  restart: unless-stopped
  environment:
    - DB_TYPE=postgresdb
    - DB_POSTGRESDB_HOST=postgres
    - DB_POSTGRESDB_PORT=5432
    - DB_POSTGRESDB_DATABASE=n8n
    - DB_POSTGRESDB_USER=n8n
    - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
    - EXECUTIONS_MODE=queue
    - QUEUE_BULL_REDIS_HOST=redis
    - QUEUE_BULL_REDIS_PORT=6379
    - QUEUE_HEALTH_CHECK_ACTIVE=true
    - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
    - GENERIC_TIMEZONE=Europe/Helsinki
    - N8N_LOG_LEVEL=info
    - EXECUTIONS_DATA_PRUNE=true
    - EXECUTIONS_DATA_MAX_AGE=336
  depends_on:
    postgres:
      condition: service_healthy
    redis:
      condition: service_healthy

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: n8n
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n"]
      interval: 5s
      timeout: 5s
      retries: 10

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --maxmemory-policy noeviction --appendonly yes
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10

  n8n-main:
    <<: *shared
    ports:
      - "5678:5678"
    environment:
      - N8N_HOST=n8n.example.com
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.example.com/
      - OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true
    volumes:
      - n8n_data:/home/node/.n8n

  n8n-worker:
    <<: *shared
    command: worker --concurrency=10
    deploy:
      replicas: 3

  n8n-webhook:
    <<: *shared
    command: webhook
    deploy:
      replicas: 2

volumes:
  postgres_data:
  redis_data:
  n8n_data:

Muutama huomio yllä olevaan. OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true pakottaa editorin "Execute workflow" -napin ajamaan työnkulun workerissa, koska muuten manuaalisuoritukset ajautuvat main-prosessiin ja tukkivat editorin uudelleen. EXECUTIONS_DATA_MAX_AGE=336 tarkoittaa 14 päivän retentionia (arvo on tunneissa), mikä on käytännössä hyvä lähtökohta useimmille GDPR-vaatimuksille. Docker-imagen versio kannattaa aina lukita. Rehellisesti sanottuna latest-tagi on varmin tapa herätä keskellä yötä rikkinäisen tuotantoympäristön ääreen.

AI Agent -noden ajaminen queue moden alla

Queue modessa ei tarvitse muuttaa mitään itse työnkulussa. AI Agent -node ja sen kaikki alinodet (Chat Model, Memory, Tool) suoritetaan täsmälleen samassa worker-prosessissa. Se on ratkaisevaa: agentin muistikonteksti pysyy yhtenäisenä koko suorituksen ajan ilman inter-process-viestintää.

Tärkeimmät asetukset AI-työnkuluille worker-tasolla:

N8N_PAYLOAD_SIZE_MAX=32          # MB, LLM-vastaukset voivat olla isoja
EXECUTIONS_TIMEOUT=1800          # 30 min, agenttiketjut kestävät
EXECUTIONS_TIMEOUT_MAX=3600      # kova katto per suoritus
N8N_DEFAULT_LOCALE=fi
NODE_OPTIONS=--max-old-space-size=2048

NODE_OPTIONS on kriittinen. Node.js:n oletusheap on 1,5 GB, ja iso RAG-työnkulku, joka lataa 500 dokumenttia vektorihakuun ennen agenttikutsua, voi triviaalisti käyttää 2 GB. Ilman tätä asetusta workeri kaatuu "JavaScript heap out of memory" -virheeseen keskellä suoritusta, ja työ jää roikkumaan Redis-jonossa "processing"-tilaan, kunnes stalled-detector poistaa sen (oletuksena 30 s).

Jos käytät MCP-palvelinta työkalulähteenä, aseta MCP-yhteydet erilliseen Tool-alinodeen sen sijaan, että kytkisit ne suoraan Chat Modeliin. Muuten yhteyden aikakatkaisut kirjautuvat pääasialliseen prompt-lokiin sen sijaan, että näkyisivät työkalukutsuina.

Chat Model -alinoden kokoonpano

Kun käytät Anthropic Claude -mallia AI Agent -nodessa, aseta maxTokens-parametri työnkulussa aina eksplisiittisesti. Oletusarvo 8192 syö nopeasti budjetin, kun agentti tekee toolCall-kierroksia. Yhdistä tähän prompt caching Claude-mallille, niin saat pitkien system-promptien kustannukset laskemaan jopa 90 %. Yhdistelmä toimii yllättävän hyvin myös silloin, kun promptit vaihtelevat käyttäjän kontekstin mukaan (kunhan cache-hakemistot pysyvät stabiileina).

Kuinka skaalata n8n workereita concurrencyn ja autoskaalauksen kanssa?

Kaksi ulottuvuutta pitää säätää itsenäisesti: workereiden lukumäärä (horisontaalinen skaalaus) ja jokaisen workerin concurrency (kuinka monta työnkulkua yksi workeri ajaa samanaikaisesti). Kaava, jota käytän lähtökohtana:

  • CPU-sidoteille työnkuluille (JSON-käsittely, kryptografia, isot Function-nodet): concurrency = 2 × vCPU per workeri.
  • I/O-sidoteille työnkuluille (HTTP-kutsut, LLM-agentit, DB-kyselyt): concurrency = 10–15 per workeri, koska ne odottavat suurimman osan ajastaan.
  • AI Agent -työnkuluille sekaisin: aloita concurrency 10:llä ja mittaa event loop lag Prometheus-metriikoista.

Kubernetesissä workereiden HorizontalPodAutoscaler kannattaa perustaa Redis-jonon pituuteen, ei CPU:hun. CPU on harhaanjohtava metriikka, koska I/O-sidonnainen workeri näyttää 5 %:n CPU:lla mutta on täysin kyllästetty 15 samanaikaisella agenttikutsulla. Käytä custom metric adapteria (esim. keda.sh) ja skaalaa Bull-jonon bull_queue_size-mittarin perusteella.

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: n8n-worker-scaler
spec:
  scaleTargetRef:
    name: n8n-worker
  minReplicaCount: 2
  maxReplicaCount: 20
  triggers:
    - type: redis
      metadata:
        address: redis:6379
        listName: bull:jobs:wait
        listLength: "20"

Erilliset webhook-vastaanottimet AI-agenteille

Kun ajat AI Agent -pohjaisia työnkulkuja Stripe-, WhatsApp- tai Slack-webhookien takana, tarvitset ehdottomasti erillisen webhook processor -kontin (n8n-webhook yllä olevassa Compose-tiedostossa). Syy on yksinkertainen: main-prosessi tekee muutakin (editori, cron-triggerit, hallinta-API), ja WhatsApp Business API odottaa 200-vastausta alle 20 sekunnissa tai retryaa saman viestin uudelleen ja uudelleen, mikä johtaa duplikoituihin agenttisuorituksiin.

Erillinen webhook processor tekee vain yhden asian: vastaanottaa HTTP-kutsun, validoi allekirjoitukset (esim. Stripe-signature), tallentaa suorituspyynnön Postgresiin ja työntää työn Redis-jonoon. Vastausaika on tyypillisesti alle 50 ms riippumatta siitä, kuinka kuormitettuja workerit ovat. Reititys hoituu load balancerissa polkuvertailulla: kaikki /webhook/* -pyynnöt menevät n8n-webhook-kontteihin, kaikki muu (editori, /rest/*) menee n8n-main-kontteihin.

Yksi harvinainen mutta tuhoisa sudenkuoppa: jos työnkulussa on "Respond to Webhook" -node ja sen suoritus kestää yli EXECUTIONS_TIMEOUT-ajan, vastaus menetetään. Käytä siis "Respond immediately" -asetusta ja lähetä varsinainen vastaus asynkronisesti (esim. WhatsApp Business API:n messages-endpointin kautta) kaikkiin agenttipohjaisiin webhook-vasteisiin.

Havainnointi, retention ja GDPR-vaatimukset

n8n tarjoaa Prometheus-metriikat, kun asettaa N8N_METRICS=true. Näihin kannattaa yhdistää vähintään nämä hälytykset: n8n_workflow_executions_failed_total-kasvunopeus, bull_queue_size yli 100 tehtävää yli 5 minuuttia, ja workereiden event loop lag yli 200 ms. Yhdistä nämä LLM-havainnointityökaluihin kuten Langfuseen tai LangSmithiin, jotka näyttävät varsinaisen LLM-jäljityksen silloin, kun workflow-taso näyttää vain epäonnistumisen.

GDPR-vaatimustenmukainen retention

Suurin sudenkuoppa GDPR:n suhteen: n8n tallentaa oletuksena kaikkien nodejen input- ja output-datan execution_data-tauluun. Tämä sisältää käyttäjien LLM-syötteet, jotka ovat usein henkilötietoja ja mahdollisesti erityisen arkaluontoisia. Kaksi asetusta ovat pakollisia:

  • EXECUTIONS_DATA_PRUNE=true ja EXECUTIONS_DATA_MAX_AGE=336 (14 päivää) poistavat vanhat suoritusdatat automaattisesti.
  • Työnkulun asetuksissa Save Data Error Execution: none ja Save Data Success Execution: none AI Agent -työnkuluille, jos et tarvitse debug-jäljitystä.

Kun execution_entity-taulu kasvaa yli 20 miljoonan rivin (tyypillinen kynnys 50 000 päivittäistä suoritusta), pruning alkaa itse hidastua kirjoituskuormituksen alla. Ratkaisu on partitioida taulu kuukausittain createdAt-sarakkeen mukaan käyttäen PostgreSQL:n natiivia partitiointia ja pudottaa vanhat partitiot suoraan DROP TABLE-komennolla. Se on 100× nopeampi kuin DELETE.

Yleisiä sudenkuoppia tuotannossa

Kolme ongelmaa, joita olen nähnyt jokaisessa yli 20 workerin asennuksessa:

  1. Puuttuva Redis-persistenssi. Jos Redis käynnistyy uudelleen ilman AOF-persistenssiä (--appendonly yes), kaikki jonossa olevat työt katoavat. Käytä AOF-persistenssiä ja seuraa levytilan käyttöä.
  2. Yhteinen credentials-tietokanta staging- ja tuotantoympäristöjen välillä. Kaikki kolme jaettua Postgres-tietokantaa, jotka olen nähnyt, on rikottu ainakin kerran. Joku vaihtaa staging-credentialsin, ja tuotannon työnkulut alkavat käyttää testipääsyä oikeaan Stripe-tiliin. Erottele ehdottomasti.
  3. SIGKILL ennen graceful shutdownia. Kubernetesin oletus terminationGracePeriodSeconds on 30 s. AI-agentit voivat helposti ajaa yli sen, joten aseta se vähintään 320:een ja käytä preStop-hookia, joka odottaa "n8n worker is stopping" -lokiviestiä.

Tarkempi lista virityksestä löytyy n8n:n virallisesta queue mode -dokumentaatiosta, ja Docker-imagen viimeisimmät versiot päivityksineen ovat Docker Hubissa. Kun otat käyttöön uusia versioita tuotantoon, päivitä aina ensin worker-replicat yksitellen ja main viimeisenä. Muuten Postgres-migraatiot voivat ajaa hetken aikaa vanhaa skeemaa oletettaville workereille.

Usein kysytyt kysymykset

Tarvitseeko n8n queue mode Redisin?

Kyllä, Redis 6.0 tai uudempi on pakollinen. Se toimii Bull-jonokirjaston viestinvälittäjänä main- ja worker-prosessien välillä; ilman Redisiä queue mode ei käynnisty lainkaan.

Voiko n8n queue moden asentaa SQLite-tietokannalla?

Ei. Queue mode vaatii PostgreSQL 14+ -tietokannan, koska useat workerit kirjoittavat samanaikaisesti execution_entity-tauluun. SQLite-lukituskonteksti ei salli tätä, ja n8n hylkää käynnistyksen selkeällä virheellä.

Kuinka monta workeria tarvitsen 10 000 päivittäiselle suoritukselle?

Karkea nyrkkisääntö: I/O-painotteille AI-työnkuluille 3–5 workeria concurrencyllä 10 riittää tähän kuormaan hyvin, olettaen 2 vCPU per workeri. Mittaa Bull-jonon pituutta 15 minuutin keskiarvona ja skaalaa, kun se pysyy yli 20:ssä.

Mikä on ero n8n webhook processorin ja main-prosessin välillä?

Main-prosessi tarjoilee editorin, REST-API:n ja hallinnoi cron-triggeriä. Webhook processor on erillinen n8n-kontti, joka ajetaan "n8n webhook" -komennolla. Se vastaanottaa vain HTTP-webhook-kutsut, työntää työn Redis-jonoon ja vastaa 200:lla, tyypillisesti alle 50 ms:ssä.

Voiko n8n:n AI Agent -noden ajaa Ollama-mallilla self-hosted-ympäristössä?

Kyllä. Chat Model -alinodena on Ollama-vaihtoehto, joka yhdistyy paikalliseen Ollama-instanssiin (esim. http://ollama:11434). Aseta EXECUTIONS_TIMEOUT vähintään 1800 sekuntiin, koska paikalliset mallit ovat huomattavasti hitaampia kuin API-pohjaiset.

Miten päivitän n8n-version queue mode -tuotannossa turvallisesti?

Ota ensin Postgres-varmuuskopio. Päivitä main-kontti viimeisenä, koska Postgres-skeeman migraatiot ajetaan main-käynnistyksen yhteydessä, ja workerit tarvitsevat sen jälkeen uudelleenkäynnistyksen. Tee blue/green Kubernetesissä workereille yksi replica kerrallaan, jotta jonossa olevat työt eivät katoa.

Tietoa Kirjoittajasta Diego Fernandez

Diego ran platform engineering at a 200-person Berlin fintech for five years, where he reluctantly became the in-house n8n expert after the ops team's self-hosted instance grew to 600 active workflows. He left in 2024 to consult independently, mostly helping European SaaS companies migrate brittle Zapier sprawl onto self-hosted n8n with proper version control and CI. His writing focuses on the operational side most agent tutorials ignore: running n8n behind a queue worker pool, secrets rotation for 30+ API integrations, GDPR-compliant logging of LLM inputs, and the Postgres tuning required when your workflow history table hits 50 million rows. He's a regular contributor to the n8n community forum and maintains a small open-source library for testing LangChain chains against fixture-based eval sets. Eleven years in backend and platform work. Based in Lisbon.