Skip to main content
The Memory state adapter stores subscriptions, locks, and cache in-process memory. Use this for local development and testing only — state is lost on restart and not shared across instances.
Never use MemoryStateAdapter in production. It logs a warning when NODE_ENV=production. Use Redis or ioredis for production deployments.

Installation

Basic Setup

Configuration

createMemoryState()

Creates an in-memory state adapter. No configuration required.

When to Use

  • Local development - Fast iteration without external dependencies
  • Unit tests - Isolated test environments
  • Integration tests - Predictable state for CI/CD
  • Demos and prototypes - Quick proof-of-concepts
  • Production - State lost on restart
  • Serverless - Each instance has separate state
  • Multi-instance deployments - No shared state
  • Long-running subscriptions - Subscriptions lost on redeploy

How It Works

The adapter stores state in JavaScript data structures:

Storage Lifecycle

  1. Startup - Data structures are empty
  2. Runtime - Subscriptions, locks, and cache accumulate in memory
  3. Shutdown - All state is lost (cleared on disconnect)
  4. Restart - Process starts fresh with empty state
Unlike Redis adapters, MemoryStateAdapter does NOT persist state across restarts. Users will need to re-subscribe to threads after deployment.

Thread Subscriptions

Subscriptions are stored in an in-memory Set:

Subscription Behavior

Distributed Locking

Locks are stored in an in-memory Map with automatic expiration:

Lock Cleanup

Expired locks are automatically cleaned:
Memory locks work perfectly for single-instance development. In production with multiple instances, use Redis to share locks across processes.

Caching

Cache entries support optional TTL:

Cache Storage

Expired values are lazily cleaned on access:

Connection Management

The adapter implements connect() and disconnect() for interface compatibility:

Production Warning

When NODE_ENV=production:

Testing Utilities

The adapter exposes internal methods for testing:
These methods are prefixed with _ to indicate they’re for testing only. Do NOT use them in production code.

Example: Unit Testing

Example: Integration Tests

Limitations

State is lost on:
  • Process restart
  • Application redeploy
  • Crash or unexpected shutdown
Workaround: Use Redis for production.
Each process/instance has isolated state:
  • Serverless functions don’t share subscriptions
  • Horizontal scaling creates separate state per replica
  • Load balancers route to instances with different state
Workaround: Use Redis for shared state across instances.
All state accumulates in memory:
  • Subscriptions never expire (until disconnect)
  • Cache entries with no TTL persist forever
  • Long-running processes can grow memory
Workaround: Periodically call disconnect() and connect() to clear, or use Redis.
Expired cache entries and locks are only cleaned:
  • On access (lazy cleanup)
  • When acquiring new locks
Workaround: This is fine for development. Redis handles TTL automatically.

Migration to Production

When ready for production, swap to Redis:
1

Set up Redis

Use a hosted provider (Vercel KV, Upstash, Railway) or run locally:
2

Install Redis adapter

3

Update configuration

4

Set environment variable

5

Re-subscribe threads

Existing in-memory subscriptions don’t transfer. Users must @-mention your bot again.

Environment-Based Setup

Use environment variables to switch adapters:
Now:
  • Local development - No REDIS_URL → uses Memory
  • Production - REDIS_URL set → uses Redis

Debugging

View State Counts

Reset State

Next Steps

Redis Adapter

Upgrade to production-ready Redis

State Overview

Learn about subscriptions and locking

Testing

Unit testing strategies

ioredis Adapter

Advanced Redis with Cluster support