Call
Home>Blogs & Insights>AI Agent Memory Storage: PostgreSQL, Vector Databases, Redis, and Hybrid Architectures
AI Agent Memory

AI Agent Memory Storage: PostgreSQL, Vector Databases, Redis, and Hybrid Architectures

A practical guide to storing AI agent memory: when PostgreSQL should be the canonical store, when pgvector is enough for semantic recall, where Redis fits for hot/session state, when a dedicated vector database is justified, and how to design hybrid memory with deletion, versioning, tenancy, and embedding migrations.

March 14, 2026
15 min read
4 views
Lofingo Team
AI Agent Memory Storage: PostgreSQL, Vector Databases, Redis, and Hybrid Architectures

Agent memory is often discussed as if the first design decision were “which vector database should we use?”

That is usually the wrong starting point.

Memory contains different kinds of data with different correctness and lifecycle requirements:

  • structured user preferences
  • task checkpoints
  • past experiences
  • semantic notes
  • large artifacts
  • temporary conversation state
  • searchable historical episodes

Those things do not all belong in the same storage engine.

A better architecture starts by asking:

> What is the canonical form of this memory, how will it be updated or deleted, and which indexes are only derived views for retrieval?

In many production systems, PostgreSQL or another durable transactional store remains the source of truth, while vector search, Redis, and object storage are used selectively around it.


Start by separating canonical memory from retrieval indexes

Suppose the agent remembers:

User prefers Go examples.

You may store a canonical record such as:

{
  "memory_id": "mem_123",
  "scope": "user:42",
  "type": "preference",
  "key": "example_language",
  "value": "Go",
  "source": "explicit_user_statement",
  "version": 3,
  "created_at": "...",
  "updated_at": "...",
  "deleted_at": null
}

Then you might generate an embedding from the text and add it to a semantic index.

The embedding is not necessarily the canonical memory.

It is a derived retrieval representation.

That distinction makes updates and deletion far easier to reason about.

Canonical memory record
        │
        ├── structured lookup
        ├── audit/history
        └── embedding/search index

If the memory changes, update the source record and regenerate the derived index entry.


Match memory type to storage behavior

A useful first map looks like this:

Memory/data typeGood default storage
User preferences / structured factsPostgreSQL or document DB
Durable task/run checkpointsRelational/transactional store
Semantic long-term recallPostgres + pgvector or vector/search engine
Fast session/working stateRedis or durable low-latency KV depending requirements
Large reports/files/transcriptsObject storage
Append-only detailed run historyEvent/log store or relational append-only table
Search indexDerived vector/lexical index

The goal is not to use all of them.

It is to avoid making one database pretend to be all of them.


PostgreSQL is a strong default canonical memory store

For many SaaS/agent products, PostgreSQL already solves most of the difficult memory-management requirements:

  • transactions
  • tenant-scoped queries
  • constraints
  • versioning
  • joins
  • audit metadata
  • soft deletion
  • TTL/expiry workflows
  • backups
  • access control through application logic

A simple memory schema might look like:

CREATE TABLE agent_memories (
    id              uuid PRIMARY KEY,
    tenant_id       uuid NOT NULL,
    user_id         uuid,
    agent_id        uuid,
    memory_type     text NOT NULL,
    memory_key      text,
    content         text NOT NULL,
    source_type     text NOT NULL,
    source_id       text,
    confidence      numeric,
    version         bigint NOT NULL DEFAULT 1,
    created_at      timestamptz NOT NULL DEFAULT now(),
    updated_at      timestamptz NOT NULL DEFAULT now(),
    expires_at      timestamptz,
    deleted_at      timestamptz
);

You can then create ordinary indexes for the most deterministic access paths:

CREATE INDEX agent_memories_user_idx
ON agent_memories (tenant_id, user_id, memory_type)
WHERE deleted_at IS NULL;

A query such as:

What is this user's preferred language?

may not need vector search at all.

A key lookup is faster, cheaper, and more deterministic.


Do not use semantic search when an exact lookup exists

This is one of the most common memory mistakes.

If memory has a stable key:

preferred_timezone
billing_currency
response_language

query the key.

Do not embed:

"The user's preferred timezone is Asia/Kolkata"

and hope nearest-neighbor search retrieves the right one every time.

Semantic retrieval is valuable for fuzzy questions such as:

Have we seen a similar migration problem before?
What did the user previously decide about deployment architecture?
Which past incident resembles this failure pattern?

Use exact storage for exact state and semantic search for semantic recall.


pgvector: semantic memory without another database

pgvector adds vector similarity search to PostgreSQL.

That can be a strong fit when:

  • PostgreSQL already stores the canonical memory
  • the vector corpus is manageable on your PostgreSQL infrastructure
  • transactional metadata and semantic retrieval need to live close together
  • you want one operational database instead of another stateful service

A table could include an embedding column:

ALTER TABLE agent_memories
ADD COLUMN embedding vector(1536);

Then semantic recall can combine vector ordering with normal relational filters:

SELECT id, content
FROM agent_memories
WHERE tenant_id = $1
  AND user_id = $2
  AND deleted_at IS NULL
ORDER BY embedding <=> $3
LIMIT 10;

The filtering is as important as the vector distance.

Memory retrieval should almost always be scoped before results reach the agent.


Exact vs approximate vector search

pgvector supports exact nearest-neighbor search by default.

It also supports approximate indexes such as:

  • HNSW
  • IVFFlat

These trade some recall characteristics for better search performance at scale.

HNSW

pgvector documents HNSW as generally offering a better speed/recall query trade-off than IVFFlat, at the cost of slower index construction and higher memory use.

IVFFlat

IVFFlat has lighter build characteristics but requires training/list configuration and careful probe tuning for recall.

The important point is not which acronym is “best.”

It is:

> Approximate search parameters must be tuned against your memory-retrieval evals, not copied from a blog benchmark.


Filtering can change vector-search recall

Memory retrieval almost always has filters:

tenant
user
agent
memory type
expiry
permission scope

With approximate vector indexes, filtering can interact with recall because candidate vectors may be scanned before the SQL filter removes rows.

pgvector provides several approaches such as:

  • ordinary indexes on filter columns
  • partial indexes
  • table partitioning
  • iterative index scans

This matters especially for multi-tenant memory.

A global ANN index containing every tenant's memories may have different performance/recall behavior from tenant-partitioned data.

Do not evaluate vector search only on an unfiltered benchmark.


Multi-tenancy belongs in the storage model

Every memory should have an explicit ownership scope.

At minimum:

tenant_id
user_id or principal
memory namespace/type

Never rely on the model prompt to say:

Only use memories belonging to this user.

The storage query should make cross-tenant retrieval impossible by construction.

Depending on scale and isolation requirements, you might use:

  • shared tables with strict tenant predicates
  • partitioning by tenant/group
  • separate schemas/databases for higher isolation
  • separate vector collections/namespaces

The architecture should be consistent with your broader SaaS tenancy model.


Redis: excellent for hot state, but define durability carefully

Redis can be useful for memory workloads because it provides very low-latency data access, TTLs, rich data structures, and vector search capabilities.

Redis vector search can operate over data stored in hashes or JSON and combine vector similarity with metadata filtering.

That makes Redis useful for workloads such as:

hot session state
working memory
short-lived conversation summaries
fast recent-memory recall
cached memory retrieval results
semantic search where Redis is already part of the platform

But “stored in Redis” should not automatically mean “this is our permanent source of truth.”

If the memory must survive incidents, rebuilds, or topology changes with strong durability expectations, explicitly decide whether Redis is:

canonical durable memory

or:

hot/cache/index layer derived from durable storage

For many systems, the second role is easier to operate safely.


TTL is especially useful for working memory

Not every memory should survive forever.

Redis-style TTL semantics map naturally to ephemeral state such as:

current research plan
recently accessed entity cache
short-lived conversation scratch data
temporary approval context

For durable relational memory, you can implement equivalent lifecycle behavior with an expires_at field and cleanup/archive jobs.

The important principle is that lifetime belongs in the data model.

Do not let old temporary state become accidental long-term memory because nobody built expiry.


Dedicated vector databases: use them when the workload justifies them

Dedicated vector/search platforms become attractive when semantic retrieval itself is a major workload.

Possible reasons include:

  • very large vector collections
  • high query concurrency
  • specialized filtering/search requirements
  • operational separation from the transactional database
  • distributed vector indexing at scale
  • managed vector-service preference

Examples include systems such as Qdrant, Weaviate, Pinecone, and Milvus.

But a dedicated vector database creates another production system to operate:

index freshness
backups/snapshots
replication
multi-tenancy
monitoring
embedding migrations
deletions
cost

If PostgreSQL + pgvector comfortably serves the workload, adding another database just because “AI memory needs a vector DB” is overengineering.


Vector index as derived state

A robust pattern is:

Canonical Memory Store
(PostgreSQL)
       │
       ├── exact lookup
       ├── lifecycle + audit
       └── change event / job
                 │
                 ▼
         Vector Search Index

The vector index can then be rebuilt from the canonical store if necessary.

This gives you a clean answer to questions such as:

What happens if the embedding index is corrupted?
How do we delete a user's memory?
How do we migrate to a new embedding model?

You still need synchronization, but ownership is clear.


Object storage for large memory artifacts

Not all memory belongs in rows.

Long-running agents may produce:

  • reports
  • datasets
  • code snapshots
  • PDFs
  • large session ledgers
  • generated artifacts

Store large objects in object/file storage and keep metadata + references in the canonical database.

For example:

{
  "artifact_id": "art_123",
  "tenant_id": "t1",
  "kind": "incident_report",
  "object_key": "tenant/t1/reports/art_123.md",
  "summary": "...",
  "embedding_status": "indexed"
}

Then index only the searchable text/summary/chunks needed for semantic recall.

Do not turn the vector store into blob storage.


Episodic history may deserve append-only storage

Agent experiences can be useful later:

what happened
what action was taken
what evidence was used
what outcome occurred

A detailed run ledger may be append-only while a separate distilled memory record captures the lesson.

Example:

raw run events
    ↓
immutable/auditable history

background consolidation
    ↓
compact episodic memory
    ↓
semantic retrieval index

This keeps forensic detail separate from the small memory representation shown to the model.


A practical hybrid architecture

A strong default for many agent products looks like this:

                         ┌─────────────────────┐
                         │  Object Storage     │
                         │ reports / artifacts │
                         └─────────▲───────────┘
                                   │
Agent / App                        │
    │                              │
    ▼                              │
Memory Policy Layer                │
    │                              │
    ▼                              │
┌────────────────────────────────────────────┐
│ PostgreSQL / Canonical Memory Store        │
│ structured facts, scope, provenance, TTL,  │
│ versions, deletion, task checkpoints       │
└───────────────┬────────────────────────────┘
                │
       ┌────────┴─────────┐
       ▼                  ▼
 Redis hot layer      Semantic index
 sessions/cache       pgvector or dedicated DB
       │                  │
       └────────┬─────────┘
                ▼
        Context Retrieval
                ▼
               LLM

You may not need every box.

Start with the canonical store and add layers only when measurements justify them.


Memory write path

A safe write flow can look like:

interaction produces memory candidate
        ↓
memory policy decides whether it should persist
        ↓
validate scope / sensitivity / provenance
        ↓
write canonical record transactionally
        ↓
queue index update
        ↓
generate embedding
        ↓
upsert derived semantic index

For high-value memories, canonical persistence should not depend on the vector index being available in the same synchronous request.

The index can catch up asynchronously if your product semantics allow it.


Memory read path

A retrieval flow may combine exact and semantic access:

request
   ↓
identify needed memory type
   ↓
┌───────────────┬──────────────────┐
exact key lookup│ semantic recall  │
└───────────────┴──────────────────┘
          ↓
permission / expiry filtering
          ↓
confidence + recency ranking
          ↓
small memory set
          ↓
LLM context

The system does not need semantic search for every request.


Memory deletion is a distributed consistency problem

Suppose a user deletes a memory.

You may have copies in:

canonical database
Redis cache
vector index
search index
object storage
backups

At minimum, the online path should make deleted data unreachable immediately.

A deletion workflow can be:

mark/delete canonical memory
        ↓
revoke from normal reads
        ↓
remove cache entry
        ↓
remove vector/search entry
        ↓
remove or tombstone related artifacts where required
        ↓
record completion/audit state

If asynchronous deletion is used, track it explicitly rather than hoping every index eventually catches up.


Tombstones can help synchronize deletion

Instead of physically deleting the canonical record instantly, some systems use a tombstone:

deleted_at = timestamp
version = version + 1

Derived-index workers can consume that change and remove stale entries.

The application query filters deleted records immediately.

Whether you retain tombstones depends on privacy, compliance, and audit requirements, but the synchronization pattern is useful.


Embedding versions belong in the schema

Embedding models change.

Never store a vector without knowing which model/version produced it.

Useful metadata includes:

embedding_model
embedding_version
dimension
created_at
source_memory_version

Then an embedding migration can be deliberate:

v1 index serving production
        ↓
create v2 vectors in background
        ↓
compare retrieval evals
        ↓
switch reads
        ↓
retire v1

Do not overwrite the only working index before you know the new model performs better.


Memory updates need version control

Imagine this sequence:

09:00 user says preferred language = English
09:05 background worker embeds that memory
09:06 user changes preference = Hindi
09:07 old worker writes stale embedding after new value

Use version numbers or optimistic concurrency so derived updates can verify they are indexing the current canonical version.

Example:

memory version 4
embedding job expects version 4

if canonical version != 4:
    discard stale job

This prevents out-of-order async workers from resurrecting stale memory.


Backups must cover the canonical layer

If the semantic index is rebuildable, its backup requirements may differ from the canonical store.

Ask:

If this database disappears, can we recreate it?

For canonical memory:

usually no → strong backup/PITR strategy.

For a vector index generated entirely from canonical records:

possibly yes → snapshots may speed recovery, but the source still exists.

This distinction can simplify disaster recovery.


Redis cache failure should not erase durable memory

If Redis is only the hot layer, the system should degrade to the durable store.

Design for:

Redis unavailable
→ memory lookups slower
→ durable store still authoritative

not:

Redis unavailable
→ agent forgot the user permanently

If Redis is canonical by design, then its durability and recovery configuration must match that responsibility.


Retrieval ranking should use more than vector similarity

Long-term memory relevance can depend on:

  • semantic similarity
  • explicit key match
  • scope
  • confidence
  • recency
  • memory type
  • importance
  • expiration

A simple ranking model might conceptually combine:

semantic relevance
+ recency weight
+ confidence
+ task-type compatibility

Do not assume the nearest vector is automatically the memory the model should see.


Do not inject too much memory

Storage can scale to millions of records. The model context should not.

Retrieve the smallest useful set.

A request about deployment architecture does not need:

favorite UI color
previous restaurant search
old unrelated project decisions

Memory quality is partly a storage problem and partly a context-selection problem.


Dedicated vector database vs pgvector: a practical decision

Start with PostgreSQL + pgvector when

  • PostgreSQL already exists
  • memory volume is modest/medium
  • relational filters and transactions matter
  • one datastore simplifies operations
  • vector search is supporting the product, not the product itself

Consider a dedicated vector system when

  • semantic search is a major high-scale workload
  • vector corpus/concurrency is large
  • specialized distributed indexing/features materially help
  • independent scaling is valuable
  • your team is willing to operate another stateful service

Do not migrate because of model parameter count or AI hype. Measure retrieval latency, recall, index growth, and operational load.


Production checklist

Before shipping a memory storage architecture, verify:

  • Canonical memory ownership is explicit
  • Exact facts use deterministic lookup where possible
  • Vector search is used only where semantic recall helps
  • Every memory has tenant/user/application scope
  • Deletion propagates to caches and derived indexes
  • Embedding model/version is stored
  • Async index jobs cannot overwrite newer memory versions
  • TTL/expiry exists for temporary memories
  • Redis's durability role is explicit
  • Large artifacts live outside ordinary vector rows
  • Backups cover the true source of truth
  • Semantic index can be rebuilt or has a recovery strategy
  • Retrieval tests include real tenant filters
  • Memory ranking considers more than vector distance
  • Context selection limits how much memory reaches the model

Final takeaway

AI memory storage should look like good data architecture, not an “AI database” shopping list.

For many products, the simplest robust path is:

PostgreSQL → canonical memory and durable state
pgvector   → semantic recall when scale fits
Redis      → hot/session/ephemeral state and cache
Object storage → large artifacts
Dedicated vector DB → only when semantic-search scale/features justify it

The exact products can change. The responsibility boundaries should remain stable.

> Keep durable truth in a store you can update, audit, back up, and delete from reliably. Treat embeddings and vector indexes as retrieval structures unless you have a deliberate reason to make them the source of truth.

That principle makes memory easier to evolve as models, embedding systems, and retrieval technology change.


Official references

Tags:AI Agent MemoryPostgreSQLpgvectorRedisVector DatabaseLLMMemory ArchitectureAI InfrastructureSemantic SearchState Management
Lofingo Team
Written by

Lofingo Team

Official writer and content strategist at Lofingo. Dedicated to delivering high-quality insights on technology and market trends.

Share your thoughts:

Discussion (0)

No comments yet. Be the first to start the discussion!