Elasticsearch
The Elasticsearch storage implementation provides agent memory, workflow snapshot, and score storage on top of an Elasticsearch cluster using the official @elastic/elasticsearch client. It shares the same connection configuration as ElasticSearchVector, so a single cluster (and even a single client instance) can serve both agent memory and semantic recall.
ElasticSearchStore currently implements the memory, workflows, and scores storage domains.
InstallationDirect link to Installation
npm install @mastra/elasticsearch
UsageDirect link to Usage
Using a URLDirect link to Using a URL
import { ElasticSearchStore } from '@mastra/elasticsearch'
const storage = new ElasticSearchStore({
id: 'elasticsearch-storage',
url: 'http://localhost:9200',
})
await storage.init()
Using authenticationDirect link to Using authentication
import { ElasticSearchStore } from '@mastra/elasticsearch'
const storage = new ElasticSearchStore({
id: 'elasticsearch-storage',
url: 'https://my-cluster.example.com:9200',
auth: { apiKey: process.env.ELASTICSEARCH_API_KEY! },
})
auth also accepts { username, password } or { bearer }.
Using a pre-configured clientDirect link to Using a pre-configured client
For advanced configurations (cloud IDs, TLS options, custom transport), pass a pre-configured client. The same client can be shared with ElasticSearchVector:
import { Client } from '@elastic/elasticsearch'
import { ElasticSearchStore, ElasticSearchVector } from '@mastra/elasticsearch'
const client = new Client({
node: 'https://my-cluster.example.com:9200',
auth: { apiKey: process.env.ELASTICSEARCH_API_KEY! },
})
const storage = new ElasticSearchStore({ id: 'elasticsearch-storage', client })
const vector = new ElasticSearchVector({ id: 'elasticsearch-vector', client })
When you provide your own client, storage.close() does not close it — you remain responsible for its lifecycle.
ParametersDirect link to Parameters
id:
url?:
http://localhost:9200)auth?:
{ apiKey }, { username, password }, or { bearer }client?:
@elastic/elasticsearch) for advanced setupsdisableInit?:
storage.init() explicitly before useYou must provide either url or client. These options are mutually exclusive.
Additional NotesDirect link to Additional Notes
Index StructureDirect link to Index Structure
Each Mastra storage table maps to one Elasticsearch index of the same name (for example mastra_threads, mastra_messages, mastra_workflow_snapshot, mastra_scorers). Records are stored as opaque JSON documents with a keyword key field, so no index mappings need to be managed manually — indexes are created on first use.
ConsistencyDirect link to Consistency
Elasticsearch search is near-real-time. All writes are performed with an immediate refresh so subsequent reads and searches observe them, and point reads use real-time get-by-ID lookups.
Closing ConnectionsDirect link to Closing Connections
When shutting down your application, close the connection:
await storage.close()
This only closes clients created by ElasticSearchStore from a url; user-provided clients are left open.
Usage ExampleDirect link to Usage Example
Adding memory to an agentDirect link to Adding memory to an agent
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { ElasticSearchStore } from '@mastra/elasticsearch'
export const elasticsearchAgent = new Agent({
id: 'elasticsearch-agent',
name: 'Elasticsearch Agent',
instructions:
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
model: 'openai/gpt-5.6-sol',
memory: new Memory({
storage: new ElasticSearchStore({
id: 'elasticsearch-agent-storage',
url: process.env.ELASTICSEARCH_URL!,
auth: { apiKey: process.env.ELASTICSEARCH_API_KEY! },
}),
options: {
lastMessages: 10,
},
}),
})
Using with Mastra instanceDirect link to Using with Mastra instance
import { Mastra } from '@mastra/core'
import { ElasticSearchStore } from '@mastra/elasticsearch'
const storage = new ElasticSearchStore({
id: 'mastra-storage',
url: 'http://localhost:9200',
})
const mastra = new Mastra({
storage, // init() called automatically
})
If using storage directly without Mastra, call init() explicitly:
import { ElasticSearchStore } from '@mastra/elasticsearch'
const storage = new ElasticSearchStore({
id: 'elasticsearch-storage',
url: 'http://localhost:9200',
})
await storage.init()
// Access domain-specific stores via getStore()
const memoryStore = await storage.getStore('memory')
const thread = await memoryStore?.getThreadById({ threadId: '...' })