⏱️ 16 min read · 📥 Free importable chat bot with memory included
Last month a client showed me his "finished" support bot. It answered the first question beautifully — then asked for the customer's name again on message two. On message three it apologized for a refund it had promised two minutes earlier, because it no longer remembered promising it.
That bot didn't have a logic problem. It had a memory problem — and memory in n8n is the least-understood part of AI agents. Most guides tell you to "just add memory" and stop there. This one explains the four memory types, the session ID trap that silently merges your users' conversations, and ends with a working template you can import today.
n8n gives your AI agent memory through memory nodes attached to the AI Agent's memory connection. There are four: Simple Memory (inside one execution), Window Buffer Memory (the last N exchanges, persists internally), Postgres Chat Memory (conversations in your own database), and Redis Chat Memory (shared memory across queue-mode workers).
The make-or-break detail is the session key: bind it to a per-user value (a chat ID, a sender ID) or every user shares one memory and your bot tells strangers each other's business. The full setup is in sections 4–7, and the multi-user trap gets section 2 all to itself.
On this page
- The 4 Memory Types at a Glance
- The Multi-User Trap: Session IDs
- Memory 1: Simple Memory
- Memory 2: Window Buffer Memory
- Memory 3: Postgres Chat Memory
- Memory 4: Redis Chat Memory
- Choosing the Right Memory
- Beyond Chat Logs: Long-Term & Semantic Memory
- Free: Importable Chat Bot with Memory
- 7 Common Errors + Fixes
- Privacy & Data Checklist
- FAQ
- Sources & References
1. The 4 Memory Types at a Glance
n8n ships four memory nodes for the AI Agent. They differ in three questions: how much they remember, how long it survives, and who can read it:
| Memory node | Remembers | Survives | Best for |
|---|---|---|---|
| Simple Memory | Context within one execution | Nothing — dies with the execution | Prototypes, testing the agent before going live |
| Window Buffer Memory | The last N exchanges per session | n8n's internal store — survives executions, not restarts | Most single-instance chatbots |
| Postgres Chat Memory | Full conversation per session | Your PostgreSQL database — survives everything | Production bots; memory you can query, back up, and audit |
| Redis Chat Memory | Full conversation per session | Your Redis server | Queue mode / multiple workers sharing memory |
One mental model that saves hours: memory is a bucket with a key on it. Every node above stores messages under a session key. Same key = same bucket. Different key = different bucket. Every memory problem in production is, at its root, a key problem.
2. The Multi-User Trap: Session IDs
This is the bug that makes support bots confess other customers' orders. The memory node's session key defaults to a fixed value — and a fixed value means every conversation pours into the same bucket. Three failure modes, all real, all avoidable:
| # | Mistake | What happens |
|---|---|---|
| 1 | Leaving the session key on its default | All users share one memory — the agent tells Sarah what Bob ordered |
| 2 | Using the same key expression on memory and tools, but different values | Memory looks right while tools can't find the related state |
| 3 | Attaching memory to a workflow that has no session at all | Error spam — a one-shot "summarize this article" job needs no memory |
The fix is one setting: bind the session key to a per-user expression. What that expression is depends on where your users come from:
// Session key expression examples — one of these, depending on your trigger
// Chat Trigger (n8n's built-in chat widget) — sessionId arrives automatically:
{{ $('Chat Trigger').item.json.sessionId }}
// Telegram / Slack — the sender's real ID:
{{ $('Telegram Trigger').item.json.message.from.id }}
// Custom webhook — whatever field identifies your user:
{{ $json.userId }}
Note the subtlety: when you run the same agent behind two different triggers (say, Telegram and your website widget), the same human is two different IDs in two different memories. If that matters to you, normalize the key yourself — map both to a single customer ID before the memory node.
3. Memory 1: Simple Memory
Simple Memory is the built-in node that holds the conversation inside the current execution. Within one chat session it gives the agent context; the moment the execution ends, it's gone. That makes it perfect for:
- Testing a new agent before you commit to infrastructure
- One-shot workflows where "memory" just means "use the earlier nodes' output"
- Understanding how the memory connection works, without credentials
4. Memory 2: Window Buffer Memory
Window Buffer Memory is the practical upgrade: it keeps the last N exchanges of each conversation and persists them in n8n's internal store — so a chat that spans multiple executions still flows. This is the right default for most single-instance chatbots.
The one parameter that matters is contextWindowLength — how many exchanges the agent re-reads on every message:
- Default is 5 — and it's a trap. Five exchanges is barely a greeting; your agent will "forget" things mid-conversation and users will think it's broken.
- 20–50 — the realistic range for a natural support conversation.
- The cost: every remembered exchange is re-sent to the model as tokens. 50 exchanges costs meaningfully more than 10. Section 7 has the full cost picture.
The window is a sliding cap on context, not on persistence — old messages stay stored per session; they just stop being replayed into the prompt. Pair a 30-exchange window with a periodic summary job and you get the best of both: continuity without a runaway token bill.
5. Memory 3: Postgres Chat Memory (Production)
When the conversation must survive restarts, queue-mode workers, and your own curiosity — Postgres Chat Memory writes every exchange to a table in your database. This is the memory for production bots.
Add the node to the agent's memory connection
On the AI Agent node, open the Memory connector and add Postgres Chat Memory. Attaching it as a sub-node wires it in automatically.
Select a Postgres credential and set the session key
Use the same Postgres server as your n8n database (it's already there if you followed our Docker installation guide), and bind the key to a per-user expression from section 2.
Let n8n create the table — or check the schema
On first use, the node creates its table automatically. The schema it expects looks like this:
CREATE TABLE IF NOT EXISTS public.n8n_chat_histories
(
id integer NOT NULL DEFAULT nextval('n8n_chat_histories_id_seq'::regclass),
session_id character varying(255) NOT NULL,
message jsonb NOT NULL,
CONSTRAINT n8n_chat_histories_pkey PRIMARY KEY (id)
);
session_id— which conversation the message belongs to (your key from section 2).message— the exchange itself, stored as JSON with role and content.- Automatic creation requires privileges: the database user needs
CREATEpermission on the schema. If n8n can't create the table, you'll see a permission error — error #7 in section 10.
SELECT. That's the difference between a toy bot and a system you can operate.6. Memory 4: Redis Chat Memory
Redis Chat Memory stores the same conversation data in Redis instead of Postgres. The practical difference is speed and the queue-mode story: if your workflows run across multiple workers (our Queue Mode guide sets that up), Redis memory gives every worker one shared, fast conversation store — no database round-trip per message.
Setup mirrors the Postgres node: add it to the agent's memory connection, select a Redis credential, set the session key. Choose Redis when chat latency matters and you're already running Redis for the queue; choose Postgres when auditability and backups matter more.
7. Choosing the Right Memory
| Your situation | Use | Why |
|---|---|---|
| Prototyping a new agent | Simple Memory | Zero setup, dies harmlessly |
| Single-instance chatbot, low stakes | Window Buffer Memory | Persists across executions, no credentials, cap the window at 20–50 |
| Production support bot | Postgres Chat Memory | Survives everything + queryable + backable up |
| Queue mode / multiple workers | Postgres or Redis Chat Memory | Simple Memory breaks across workers |
| Chat latency is critical, Redis already present | Redis Chat Memory | Fastest shared store |
8. Beyond Chat Logs: Long-Term & Semantic Memory
The four nodes above all store chat history — a log of what was said. Production agents often need a different kind of memory: facts that survive weeks, and answers found by meaning rather than by sequence. Two patterns cover that, and both are worth knowing before you outgrow your bot:
8.1 The Chat Memory Manager (custom patterns)
When a fixed window isn't enough, n8n's Chat Memory Manager node (@n8n/n8n-nodes-langchain.memoryManager) sits on top of any memory backend and lets you build custom behavior: summarize old turns into a rolling summary, prune stale sessions, merge memories when a user changes channels. It's the escape hatch for everything this guide can't predict — and the official n8n skills reference recommends it exactly for that.
8.2 Long-term memory via tools & vector stores
The community pattern for "remember this customer's preferences forever" is not a bigger chat log — it's a tool the agent can call: a save memory tool that writes to Google Docs, a database, or a note system, and a retrieve memory tool that searches it. Real n8n exports implement exactly this — an AI tool node for saving, a retrieval node wired back into the agent. The agent decides when to remember, instead of replaying everything every time.
The semantic version of the same idea: store embeddings in a vector store (Qdrant, Pinecone, pgvector, Supabase) and let the agent search by meaning — "what did this user say about refunds?" — instead of by keyword. In n8n this wires in through the agent's retriever/tool connections, not the memory slot. That combination — a short chat window plus a long-term store — is the architecture behind every serious support bot, and it's the subject of our upcoming RAG guide.
9. Free Template: Importable Chat Bot with Memory
A working starting point: Chat Trigger → AI Agent (OpenAI) with Postgres Chat Memory attached, session key bound to the chat's own sessionId — so every visitor gets an isolated conversation that survives restarts.
{
"name": "AI Chat Bot with Postgres Memory",
"nodes": [
{
"parameters": {
"options": {}
},
"id": "chat-trigger",
"name": "Chat Trigger",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"typeVersion": 1.1,
"position": [250, 300]
},
{
"parameters": {
"model": "gpt-4o-mini",
"options": {}
},
"id": "model",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"typeVersion": 1.1,
"position": [250, 500],
"credentials": {
"openAiApi": {
"id": "YOUR_OPENAI_CREDENTIAL_ID"
}
}
},
{
"parameters": {
"options": {
"systemMessage": "You are a friendly assistant with memory. Refer to earlier messages in the conversation when relevant."
}
},
"id": "agent",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"typeVersion": 1.7,
"position": [450, 300]
},
{
"parameters": {
"sessionIdType": "customKey",
"sessionKey": "={{ $('Chat Trigger').item.json.sessionId }}",
"contextWindowLength": 20
},
"id": "memory",
"name": "Postgres Chat Memory",
"type": "@n8n/n8n-nodes-langchain.memoryPostgresChat",
"typeVersion": 1.3,
"position": [650, 400],
"credentials": {
"postgres": {
"id": "YOUR_POSTGRES_CREDENTIAL_ID"
}
}
}
],
"connections": {
"Chat Trigger": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Postgres Chat Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true
}
}
- Two credentials to fill: OpenAI and Postgres. The session key needs nothing — it binds to the chat's own ID automatically.
- Honest version note: AI-node type versions drift between n8n releases. If the import complains, re-add the four nodes from the panel and wire them the same way — the memory configuration (key + window) is the part that matters.
- Test isolation before going live: open two browser sessions and chat in both. Ask user A "what's my name?" after user B introduced themselves — if A ever hears B's name, your session key is wrong.
- Want a Telegram front end instead? Our Telegram bot guide shows the trigger and keyboard side — combine it with this memory setup and you have a remembering bot in any messenger.
10. The 7 Most Common Errors & Fixes
| # | Error / Symptom | Cause | Fix |
|---|---|---|---|
| 1 | Key parameter is empty. Provide a key to use as session ID… |
The memory node has no session key configured | Set sessionIdType: customKey + a sessionKey expression, or select the connected Chat Trigger option (section 2) |
| 2 | no session id found / agent can't find the session |
The key expression points at a field that doesn't exist in the incoming payload | Check the trigger's actual output fields and fix the expression — inspect the incoming JSON first |
| 3 | Agent mixes conversations between users | Session key left on a fixed default — one bucket for everyone | Bind the key to a per-user expression (section 2, mistake #1) |
| 4 | Memory looks fine but tools can't find related state | Memory and tools use different session keys | Use the exact same expression on the memory node and every tool that reads session state |
| 5 | Token bill explodes after adding memory | Window too large, or an unbounded memory buffer | Cap contextWindowLength at 20–50 and summarize old turns (section 7) |
| 6 | Memory "not working" in queue mode | Simple Memory doesn't follow executions across workers | Switch to Postgres or Redis Chat Memory (sections 5–6) |
| 7 | Postgres memory errors on first run — no table | The database user lacks CREATE privileges |
Grant create rights or pre-create the n8n_chat_histories table (schema in section 5) |
11. Privacy & Data Checklist
Memory means storing conversations — which means you now hold personal data. Four habits that keep you out of trouble:
- ✅ Know where each conversation lives: n8n's internal store (Simple/Window Buffer) or your database (Postgres/Redis)
- ✅ Define retention — add a scheduled cleanup for
n8n_chat_historiesrows older than 90 days (or your policy's limit) - ✅ Give users a "forget me" path: a
/clearcommand or admin action that deletes theirsession_idrows - ✅ Back up memory data with the same rigor as workflows — our Backup guide covers the database layer
- ✅ Never put memory in a shared/self-serve bot without a privacy notice — users deserve to know the bot remembers them
12. Frequently Asked Questions
Attach a memory node — Simple Memory, Window Buffer Memory, Postgres Chat Memory, or Redis Chat Memory — to the AI Agent node's memory connection. Then bind the session key to a per-user identifier so every conversation gets its own memory bucket (sections 1–2).
Simple Memory keeps context inside the running execution — light but unreliable across restarts and workers. Postgres Chat Memory stores the conversation in a PostgreSQL table, so it survives restarts, works in queue mode, and is readable by other systems.
Because every conversation shares the same session ID — usually the default value. Bind the memory's session key to a per-user expression (the chat's sessionId, the Telegram sender ID, your own user field) and each user gets an isolated bucket (section 2).
The memory node cannot resolve a session ID from the incoming data. Either connect a Chat Trigger (which provides sessionId automatically) or set the session key to an expression that exists in your input payload (error #2 in section 10).
Not reliably. In queue mode, executions land on different workers and Simple Memory's in-execution context does not follow. Use Postgres Chat Memory or Redis Chat Memory when you run queue mode (sections 5–6).
It's the number of recent exchanges the agent keeps in context. The default is 5 — far too low for a natural conversation. Start around 20–50; higher values keep more context but consume more tokens per message (section 4).
Add a Postgres Chat Memory node to the agent's memory connection, select a Postgres credential, and set the session key. n8n creates the n8n_chat_histories table automatically — the database user needs CREATE privileges (section 5).
It depends on the memory node. Simple and Window Buffer Memory keep it inside n8n's internal store; Postgres and Redis memory keep it in your own database. If users chat with customers, treat that history as personal data — define retention and deletion rules (section 11).
Yes. Every remembered message is re-sent to the model as context on each call. A context window of 50 exchanges costs noticeably more than 10. Cap the window to what the conversation genuinely needs, and summarize old turns instead of replaying them (section 7).
Sources & References
- n8n Documentation — Memory in the AI Agent
- n8n Documentation — Postgres Chat Memory node
- n8n Official Skills — Agent memory reference
- n8n GitHub — "Key parameter is empty" memory node issue
- n8n Documentation — Memory nodes
