# Upstash Storage The Upstash storage implementation provides a serverless-friendly storage solution using Upstash's Redis-compatible key-value store. > **Pricing:** When using Mastra with Upstash, the pay-as-you-go model can result in unexpectedly high costs due to the high volume of Redis commands generated during agent conversations. We strongly recommend using a **fixed pricing plan** for predictable costs. See [Upstash pricing](https://upstash.com/pricing/redis) for details and [GitHub issue #5850](https://github.com/mastra-ai/mastra/issues/5850) for context. > **Observability Not Supported:** Upstash storage **does not support the observability domain**. Traces from the `DefaultExporter` cannot be persisted to Upstash, and Mastra Studio's observability features won't work with Upstash as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL. ## Installation **npm**: ```bash npm install @mastra/upstash@latest ``` **pnpm**: ```bash pnpm add @mastra/upstash@latest ``` **Yarn**: ```bash yarn add @mastra/upstash@latest ``` **Bun**: ```bash bun add @mastra/upstash@latest ``` ## Usage ```typescript import { UpstashStore } from "@mastra/upstash"; const storage = new UpstashStore({ id: 'upstash-storage', url: process.env.UPSTASH_URL, token: process.env.UPSTASH_TOKEN, }); ``` ## Parameters **url:** (`string`): Upstash Redis URL **token:** (`string`): Upstash Redis authentication token **prefix?:** (`string`): Key prefix for all stored items (Default: `mastra:`) ## Additional Notes ### Key Structure The Upstash storage implementation uses a key-value structure: - Thread keys: `{prefix}thread:{threadId}` - Message keys: `{prefix}message:{messageId}` - Metadata keys: `{prefix}metadata:{entityId}` ### Serverless Benefits Upstash storage is particularly well-suited for serverless deployments: - No connection management needed - Pay-per-request pricing - Global replication options - Edge-compatible ### Data Persistence Upstash provides: - Automatic data persistence - Point-in-time recovery - Cross-region replication options ### Performance Considerations For optimal performance: - Use appropriate key prefixes to organize data - Monitor Redis memory usage - Consider data expiration policies if needed ## Usage Example ### Adding memory to an agent To add Upstash memory to an agent use the `Memory` class and create a new `storage` key using `UpstashStore` and a new `vector` key using `UpstashVector`. The configuration can point to either a remote service or a local setup. ```typescript import { Memory } from "@mastra/memory"; import { Agent } from "@mastra/core/agent"; import { UpstashStore } from "@mastra/upstash"; export const upstashAgent = new Agent({ id: "upstash-agent", name: "Upstash Agent", instructions: "You are an AI agent with the ability to automatically recall memories from previous interactions.", model: "openai/gpt-5.1", memory: new Memory({ storage: new UpstashStore({ id: 'upstash-agent-storage', url: process.env.UPSTASH_REDIS_REST_URL!, token: process.env.UPSTASH_REDIS_REST_TOKEN!, }), options: { generateTitle: true, // Explicitly enable automatic title generation }, }), }); ``` ### Using the agent Use `memoryOptions` to scope recall for this request. Set `lastMessages: 5` to limit recency-based recall, and use `semanticRecall` to fetch the `topK: 3` most relevant messages, including `messageRange: 2` neighboring messages for context around each match. ```typescript import "dotenv/config"; import { mastra } from "./mastra"; const threadId = "123"; const resourceId = "user-456"; const agent = mastra.getAgent("upstashAgent"); const message = await agent.stream("My name is Mastra", { memory: { thread: threadId, resource: resourceId, }, }); await message.textStream.pipeTo(new WritableStream()); const stream = await agent.stream("What's my name?", { memory: { thread: threadId, resource: resourceId, }, memoryOptions: { lastMessages: 5, semanticRecall: { topK: 3, messageRange: 2, }, }, }); for await (const chunk of stream.textStream) { process.stdout.write(chunk); } ```