Storing Chatbot Session Data using Workflow Static Data VS Postgres

TL;DR:
I’m building a WhatsApp chatbot in n8n (via WAHA) and need to store session data (phone, last timestamp, status) to prevent spam replies and allow human takeover mode.
Options:

  • Workflow static data: fast, but may not handle large/high-traffic data safely.

  • Postgres: already in use, but may add latency if checked every trigger.
    Not using Redis due to cost/hosting.

Looking for advice on which approach is more efficient and how workflow static data behaves under load.

Hi everyone,
I’m fairly new to n8n and am currently building an automated WhatsApp customer service chatbot using a third-party API (WAHA). I’m trying to decide on the best way to store session data without using Redis.

What I Want to Achieve
I need to store session data containing:

  • Sender’s phone number

  • Last chat timestamp

  • Status (human/bot)

The session data will be used to:

  • Prevent spam replies: if a customer sends multiple short messages within a short time, the bot should reply once instead of replying to each message separately.

  • Human takeover mode: if a conversation is handed over to a human (status = human), the bot should stop replying until the status expires.

Options I’m Considering
Postgres

  • Pros: Already using it for chat history.

  • Cons: Might add latency if I have to query/update session data for every incoming message.

  • Workflow Static Data

  • Pros: Fast and simple.

  • Cons: Docs say it should only store small amounts of data, so it might not scale if many people are chatting at once.

My Current Approach
I’m using workflow static data as an array of sessions:

  • Each session = { phoneNumber, lastTimestamp } (and later status)

  • A Code node checks if another execution is already handling the same sender. If so, it stops the duplicate execution to avoid double replies.

  • I try to clean up old sessions by replacing the array with only newer sessions, but I’m not sure if my JavaScript logic is correct.

My Questions

  • Is my current static data approach efficient and reliable for high traffic?

  • Would using Postgres for session CRUD be better despite the potential latency?

  • How exactly does workflow static data behave with multiple executions and large arrays?

Any advice, examples, or corrections would be greatly appreciated!
I’m building a WhatsApp chatbot in n8n (via WAHA) and need to store session data (phone, last timestamp, status) to prevent spam replies and allow human takeover mode.
Options:

  • Workflow static data: fast, but may not handle large/high-traffic data safely.

  • Postgres: already in use, but may add latency if checked every trigger.
    Not using Redis due to cost/hosting.

Looking for advice on which approach is more efficient and how workflow static data behaves under load.

Hi everyone,
I’m fairly new to n8n and am currently building an automated WhatsApp customer service chatbot using a third-party API (WAHA). I’m trying to decide on the best way to store session data without using Redis.
What I Want to Achieve
I need to store session data containing:

  • Sender’s phone number

  • Last chat timestamp

  • Status (human/bot)

The session data will be used to:

  • Prevent spam replies: if a customer sends multiple short messages within a short time, the bot should reply once instead of replying to each message separately.

  • Human takeover mode: if a conversation is handed over to a human (status = human), the bot should stop replying until the status expires.

Options I’m Considering
Postgres

  • Pros: Already using it for chat history.

  • Cons: Might add latency if I have to query/update session data for every incoming message.

  • Workflow Static Data

  • Pros: Fast and simple.

  • Cons: Docs say it should only store small amounts of data, so it might not scale if many people are chatting at once.

My Current Approach
I’m using workflow static data as an array of sessions:

  • Each session = { phoneNumber, lastTimestamp } (and later status)

  • A Code node checks if another execution is already handling the same sender. If so, it stops the duplicate execution to avoid double replies.

  • I try to clean up old sessions by replacing the array with only newer sessions, but I’m not sure if my JavaScript logic is correct.

My Questions

  • Is my current static data approach efficient and reliable for high traffic?

  • Would using Postgres for session CRUD be better despite the potential latency?

  • How exactly does workflow static data behave with multiple executions and large arrays?

Any advice, examples, or corrections would be greatly appreciated!

Hey @Fatimah_M hope all is good.

IMHO/YMMV

If you really need an in‑memory cache, i’d still consider Redis (it is free if self hosted and very light), but you can still do great with Postgres only, IMO.

As for your questions:

  1. Is my current static data approach efficient and reliable for high traffic?

Efficient: yes (it’s in‑memory). Reliable under concurrency: no. It may have race conditions, is not atomic, and can be clobbered by parallel executions. It also doesn’t scale across instances and (most importantly) restarts predictably.

  1. Would Postgres be better despite “latency”?

Yes. With existing networking latency for you WAHA and LLM calls, the Postgres is not going to become the bottleneck (I mean it can be slow if poorly architected, but it sounds you know what you are doing). :+1:

  1. How does workflow static data behave with multiple executions and large arrays?
  • Each execution loads a snapshot and writes back on completion, so last write wins.
  • Large arrays increase memory use and serialization time; under heavy churn you risk OOM or slowdowns.
  • It’s not a lock. It’s not transactional. Use it only for tiny, ephemeral info.
1 Like

Thanks for the insights @jabbson, I just tried implementing the workflow with postgres. So far, during tests with workflow activation it works quite well and is still fast enough to not cause any issues with replying to chats.
I’ll keep redis as a consideration as it seems to be what you and a lot of other people have been using for in-memory caches.

1 Like