Mastra organizes storage into five specialized domains, each responsible for one type of data: memory, workflows, scores, observability, and agents. Mastra now supports configuring different storage providers per domain directly on the main Mastra instance using MastraStorage. We call this approach composite storage.
With composite storage, each domain can now use a different storage provider, giving you flexibility to match the storage to the type of data. For example, you might use Redis for fast access to conversational memory, PostgreSQL for workflow state and structured scores, and a specialized analytics engine like ClickHouse for observability data.
The following example configures memory, workflows, scores, and observability to use different storage providers using the latest @beta packages.
1// src/mastra/index.ts
2
3import { Mastra } from "@mastra/core";
4import { MastraStorage } from "@mastra/core/storage";
5import { UpstashStore } from "@mastra/upstash";
6import { WorkflowsPG, ScoresPG } from "@mastra/pg";
7import { ObservabilityStorageClickhouse } from "@mastra/clickhouse";
8
9export const mastra = new Mastra({
10 storage: new MastraStorage({
11 id: "composite",
12 domains: {
13 memory: new UpstashStore({
14 id: "upstash-memory",
15 url: process.env.UPSTASH_REDIS_REST_URL,
16 token: process.env.UPSTASH_REDIS_REST_TOKEN,
17 }),
18
19 workflows: new WorkflowsPG({
20 connectionString: process.env.WORKFLOW_DATABASE_URL,
21 }),
22
23 scores: new ScoresPG({
24 connectionString: process.env.SCORES_DATABASE_URL,
25 }),
26
27 observability: new ObservabilityStorageClickhouse({
28 url: process.env.CLICKHOUSE_URL,
29 username: process.env.CLICKHOUSE_USERNAME,
30 password: process.env.CLICKHOUSE_PASSWORD,
31 }),
32 },
33 }),
34});See the Composite Storage docs for full configuration options, or browse the supported storage providers.
Incremental adoption with a default store
Composite storage doesn’t require configuring every domain upfront. A default storage provider can be used, with only specific domains overridden as needed. This allows composition to be adopted incrementally without affecting existing setups.
1// src/mastra/index.ts
2
3import { Mastra } from "@mastra/core";
4import { MastraStorage } from "@mastra/core/storage";
5import { PostgresStore } from "@mastra/pg";
6
7export const mastra = new Mastra({
8 storage: new MastraStorage({
9 id: "composite",
10 default: new PostgresStore({
11 id: "pg-default",
12 connectionString: process.env.DATABASE_URL,
13 }),
14 domains: {
15 // ...
16 },
17 }),
18});When to use composite storage
Composite storage is most useful when different types of data have different performance, scaling, or operational requirements. When memory, workflows, scores, or observability place competing demands on a single database, configuring storage per domain allows each workload to use the most appropriate solution.
Why domains exist
Different types of data workloads place very different demands on storage, and some of those demands sit directly on the user’s critical path. For instance, memory and workflow snapshots are transferred during interactions, where low latency is important to avoid impacting user experience. Observability data, on the other hand, looks very different. Traces are generated continuously at high volume in the background, outside the user’s interaction path, while queries usually focus on a small, recent slice.
These differences are why Mastra models storage as separate domains. Isolating workloads by domain allows each type of data to use a storage provider that matches its latency, throughput, and scaling requirements.
Regional placement and data locality
Composite storage makes it possible to store data where it works best.

Latency-sensitive domains like memory and workflow state can be stored close to where requests are handled, while high-volume domains like observability can be stored in regions optimized for throughput and cost. This separation reduces user-visible latency, helps control infrastructure spend, and avoids forcing all data into a single regional setup.
What didn’t change?
Composite storage doesn’t change how agents, workflows, or memory are used in application code. Existing single-store setups continue to work as before, and storage operations across domains run in parallel and don’t block user interactions.
Breaking changes
Starting in @mastra/core@1.0.0-beta.16, storage.supports was removed and StorageSupports is no longer exported from @mastra/core/storage. All storage adapters now expose a uniform feature surface.
To check whether a specific storage domain is available, use .getStore() instead:
1import { mastra } from "./mastra";
2
3const storage = mastra.getStorage();
4
5const memory = await storage.getStore("memory");
6console.log(memory);
7
8const observability = await storage.getStore("observability");
9console.log(observability);Get started with MastraStorage
MastraStorage is available now in the latest @beta release. If you’re already using Mastra, you can adopt
incrementally by introducing a default store and overriding domains as needed. To try it out, update to the latest beta packages and follow the Composite Storage documentation to configure domains and supported storage providers.