Stores¶
Stores are the core implementations of the AsyncKeyValue protocol. They provide
the actual storage backend for your key-value data.
Store Categories¶
Stores are organized into three categories based on their storage location and use case:
- Local Stores: In-memory or on-disk storage local to the application
- Secret Stores: Secure storage for sensitive data in OS secret stores
- Distributed Stores: Network-based storage for multi-node applications
Stability Levels¶
Each store has a stability rating that indicates the likelihood of backwards-incompatible changes to how data is stored:
- Stable: No planned backwards-incompatible changes
- Preview: Unlikely to change in backwards-incompatible ways
- Unstable: May change in backwards-incompatible ways
- N/A: Not applicable (e.g., in-memory stores)
If you're using py-key-value for caching, stability may not matter. For long-term storage, prefer stable stores.
Local Stores¶
Local stores are stored in memory or on disk, local to the application.
| Store | Stability | Description |
|---|---|---|
| Memory | N/A | Fast in-memory storage for development and caching |
| Disk | Stable | Persistent file-based storage in a single file |
| Disk (Per-Collection) | Stable | Persistent storage with separate files per collection |
| DuckDB | Unstable | In-process SQL OLAP database with native JSON storage |
| FileTree (test) | Unstable | Directory-based storage with JSON files for visual inspection |
| Null (test) | N/A | No-op store for testing without side effects |
| RocksDB | Unstable | High-performance embedded database |
| Simple (test) | N/A | Simple in-memory store for testing |
| Windows Registry | Unstable | Windows Registry-based storage |
MemoryStore¶
Fast in-memory storage ideal for development, testing, and caching.
Installation:
Use Cases:
- Development and testing
- Fast caching
- Session storage
- Temporary data
Characteristics:
- No persistence (data lost on restart)
- Extremely fast
- No external dependencies
- Thread-safe
DiskStore¶
Persistent file-based storage using a single JSON file.
Installation:
Use Cases:
- Local caching with persistence
- Development environments
- Single-node applications
- Small datasets
Characteristics:
- Persists across restarts
- Simple file format (JSON)
- Suitable for small to medium datasets
- All data in one file
MultiDiskStore¶
Persistent storage with separate files per collection.
from key_value.aio.stores.multi_disk import MultiDiskStore
store = MultiDiskStore(directory="./cache")
Installation:
Use Cases:
- Organizing data by collection
- Better performance with many collections
- Easier to manage individual collections
Characteristics:
- One file per collection
- Better suited for many collections
- Easier collection management
- JSON-based storage
FileTreeStore¶
Directory-based storage for visual inspection and debugging.
from key_value.aio.stores.filetree import FileTreeStore
store = FileTreeStore(directory="./debug-store")
Installation:
Use Cases:
- Visual inspection of store contents
- Debugging store behavior
- Development and testing
- Understanding data structure
Characteristics:
- Collections as directories
- Keys as JSON files (
{key}.json) - Human-readable filesystem layout
- Easy to inspect and modify
- NOT for production use
Directory Structure:
Important Limitations:
- Poor performance with many keys
- No atomic operations
- No automatic cleanup of expired entries
- Filesystem path length constraints
- Subject to filesystem limitations
When to Use:
Use FileTreeStore when you need to:
- Visually inspect what's being stored
- Debug complex data structures
- Understand how the store organizes data
- Manually modify stored data for testing
When NOT to Use:
- Production environments
- High-performance requirements
- Large datasets
- Concurrent access scenarios
DuckDBStore¶
In-process SQL OLAP database with native JSON storage.
from key_value.aio.stores.duckdb import DuckDBStore
# In-memory database (default)
store = DuckDBStore()
# Persistent database
store = DuckDBStore(database_path="./my_store.duckdb")
# With existing connection
import duckdb
connection = duckdb.connect("./my_store.duckdb")
store = DuckDBStore(connection=connection)
Installation:
Use Cases:
- Analytics on stored key-value data
- Local development with SQL querying capabilities
- Applications needing both key-value and SQL access
- Data exploration and reporting
Characteristics:
- Native JSON column support for queryable values
- In-memory or persistent storage
- Standard SQL access to stored data
- Efficient timestamp handling for TTL queries
- Stable storage format: Unstable
Direct SQL Access:
DuckDB allows you to query your key-value data directly with SQL:
# After storing some data
await store.put("user:1", {"name": "Alice", "age": 30}, collection="users")
await store.put("user:2", {"name": "Bob", "age": 25}, collection="users")
# Query directly via DuckDB
result = store._connection.execute("""
SELECT key, value->>'name' as name
FROM kv_entries
WHERE collection = 'users'
""").fetchall()
RocksDBStore¶
High-performance embedded database using RocksDB.
Installation:
Use Cases:
- High-throughput applications
- Large datasets
- Performance-critical applications
Characteristics:
- Very fast reads and writes
- Efficient storage
- Requires native dependencies
- Stable storage format: Unstable
WindowsRegistryStore¶
Storage using the Windows Registry.
from key_value.aio.stores.registry import WindowsRegistryStore
store = WindowsRegistryStore(
hive="HKEY_CURRENT_USER",
registry_path="Software\\py-key-value"
)
Installation:
Use Cases:
- Windows-specific applications
- System configuration storage
- Integration with Windows settings
Characteristics:
- Windows-only
- Persists in registry
- Subject to registry limitations
- Stable storage format: Unstable
NullStore¶
No-op store that discards all data. Useful for testing.
Use Cases:
- Testing without side effects
- Disabling storage temporarily
- Performance baseline testing
SimpleStore¶
Simple in-memory store for testing.
Use Cases:
- Basic testing
- Minimal implementation reference
Secret Stores¶
Secret stores provide secure storage for sensitive data, typically using operating system secret management facilities.
| Store | Stability | Description |
|---|---|---|
| Keyring | Stable | OS-level secure storage (Keychain, Credential Manager, etc.) |
| Vault | Unstable | HashiCorp Vault integration for enterprise secrets |
KeyringStore¶
Secure storage using the operating system's keyring (macOS Keychain, Windows Credential Manager, Linux Secret Service).
from key_value.aio.stores.keyring import KeyringStore
store = KeyringStore(service_name="py-key-value")
Installation:
Use Cases:
- Storing API keys and tokens
- User credentials
- Sensitive configuration
- Encrypted local storage
Characteristics:
- OS-level encryption
- Secure by default
- Cross-platform
- Windows limitation: Strict value length limits
Important: Windows Keyring has strict limits on value length which may cause issues with large values.
VaultStore¶
Integration with HashiCorp Vault for enterprise secret management.
from key_value.aio.stores.vault import VaultStore
store = VaultStore(
url="http://localhost:8200",
token="your-token"
)
Installation:
Use Cases:
- Enterprise secret management
- Multi-environment deployments
- Centralized secret rotation
- Audit logging
Characteristics:
- Enterprise-grade security
- Centralized management
- Audit logging
- Stable storage format: Unstable
Distributed Stores¶
Distributed stores provide network-based storage for multi-node applications.
| Store | Stability | Description |
|---|---|---|
| Aerospike | Unstable | High-performance distributed NoSQL database |
| DynamoDB | Unstable | AWS DynamoDB key-value storage |
| S3 | Unstable | AWS S3 object storage |
| Elasticsearch | Unstable | Full-text search with key-value capabilities |
| Firestore | Unstable | Google Cloud Firestore key-value storage |
| Memcached | Unstable | High-performance distributed memory cache |
| MongoDB | Unstable | Document database used as key-value store |
| OpenSearch | Unstable | OpenSearch search engine with key-value capabilities |
| PostgreSQL | Unstable | PostgreSQL database with JSONB storage |
| Redis | Stable | Popular in-memory data structure store |
| Valkey | Stable | Open-source Redis fork |
AerospikeStore¶
High-performance distributed NoSQL database optimized for speed and scale.
from key_value.aio.stores.aerospike import AerospikeStore
# Using host list
store = AerospikeStore(
hosts=[("localhost", 3000)],
namespace="test",
set_name="kv-store"
)
# Or with an existing client
import aerospike
client = aerospike.client({"hosts": [("localhost", 3000)]})
client.connect()
store = AerospikeStore(client=client, namespace="test")
Installation:
Use Cases:
- High-throughput applications
- Real-time data processing
- Large-scale distributed systems
- Low-latency caching
Characteristics:
- Sub-millisecond latency
- Horizontal scaling
- Native TTL support
- Namespaces must be pre-configured on server
- Sets created automatically
- Stable storage format: Unstable
RedisStore¶
High-performance in-memory store using Redis.
from key_value.aio.stores.redis import RedisStore
store = RedisStore(url="redis://localhost:6379/0")
Installation:
Use Cases:
- Distributed caching
- Session storage
- Real-time applications
- High-throughput systems
Characteristics:
- Very fast (in-memory)
- Production-ready
- Rich feature set
- Horizontal scaling support
- Stable storage format
ValkeyStore¶
Open-source Redis fork with similar performance characteristics.
from key_value.aio.stores.valkey import ValkeyStore
store = ValkeyStore(host="localhost", port=6379)
Installation:
Use Cases:
- Same as Redis
- Open-source preference
- Redis API compatibility
Characteristics:
- Redis-compatible
- Open-source governance
- Production-ready
- Stable storage format
FirestoreStore¶
Google Cloud Firestore used as a key-value store.
from key_value.aio.stores.firestore import FirestoreStore
store = FirestoreStore(credentials=google_credentials, database="firestore-db")
Installation:
Use Cases:
- Google Cloud-native applications
- Serverless / managed infrastructure
- Existing Firestore deployments
Characteristics:
- Managed cloud database
- Document/collection model
- Stable storage format: Unstable
DynamoDBStore¶
AWS DynamoDB integration for serverless and cloud-native applications.
from key_value.aio.stores.dynamodb import DynamoDBStore
store = DynamoDBStore(
table_name="kv-store",
region_name="us-east-1"
)
Installation:
Use Cases:
- AWS-native applications
- Serverless architectures
- Global distribution
- Managed infrastructure
Characteristics:
- Fully managed
- Auto-scaling
- Global tables
- Pay-per-use pricing
- Stable storage format: Unstable
S3Store¶
AWS S3 object storage for durable, scalable key-value storage.
from key_value.aio.stores.s3 import S3Store
store = S3Store(
bucket_name="my-kv-bucket",
region_name="us-east-1"
)
Installation:
Use Cases:
- Large value storage (up to 5TB per object)
- Durable, long-term storage
- Cost-effective archival
- Multi-region replication
Characteristics:
- 99.999999999% durability
- Automatic key sanitization for S3 path limits
- Supports lifecycle policies
- Pay-per-use pricing
- Stable storage format: Unstable
ElasticsearchStore¶
Full-text search engine used as a key-value store.
from key_value.aio.stores.elasticsearch import ElasticsearchStore
store = ElasticsearchStore(
url="https://localhost:9200",
api_key="your-api-key",
index="kv-store"
)
Installation:
Use Cases:
- Applications already using Elasticsearch
- Need for search capabilities
- Analytics and logging
Characteristics:
- Search capabilities
- Distributed by default
- Rich querying
- Stable storage format: Unstable
OpenSearchStore¶
OpenSearch search engine used as a key-value store. Collections are stored in separate indices with values in flattened fields.
from key_value.aio.stores.opensearch import OpenSearchStore
# Using URL and API key
store = OpenSearchStore(
url="https://localhost:9200",
api_key="your-api-key",
index_prefix="kv_store"
)
# With existing client
from opensearchpy import AsyncOpenSearch
client = AsyncOpenSearch(hosts=["https://localhost:9200"])
store = OpenSearchStore(
opensearch_client=client,
index_prefix="kv_store"
)
Installation:
Use Cases:
- Applications already using OpenSearch
- Need for search capabilities with AWS-managed service
- Analytics and logging
Characteristics:
- Search capabilities
- Distributed by default
- Collections stored in separate indices
- Values stored in flat_object fields
- Stable storage format: Unstable
Sanitization Strategies:
OpenSearch has specific restrictions on keys and index names. Use the built-in sanitization strategies to avoid issues:
from key_value.aio.stores.opensearch import (
OpenSearchStore,
OpenSearchV1KeySanitizationStrategy,
OpenSearchV1CollectionSanitizationStrategy,
)
store = OpenSearchStore(
url="https://localhost:9200",
index_prefix="kv_store",
key_sanitization_strategy=OpenSearchV1KeySanitizationStrategy(),
collection_sanitization_strategy=OpenSearchV1CollectionSanitizationStrategy(),
)
MongoDBStore¶
Document database used as a key-value store.
from key_value.aio.stores.mongodb import MongoDBStore
store = MongoDBStore(url="mongodb://localhost:27017/test")
Installation:
Use Cases:
- Applications already using MongoDB
- Document-oriented data
- Flexible schemas
Characteristics:
- Document storage
- Rich querying
- Horizontal scaling
- Stable storage format: Unstable
PostgreSQLStore¶
PostgreSQL database with JSONB storage for flexible key-value data.
Note: PostgreSQL is async-only. This store uses asyncpg which
provides native async/await operations.
from key_value.aio.stores.postgresql import PostgreSQLStore
# Using connection URL
store = PostgreSQLStore(url="postgresql://localhost:5432/mydb")
# Using connection parameters
store = PostgreSQLStore(
host="localhost",
port=5432,
database="mydb",
user="myuser",
password="mypass"
)
async with store:
await store.put(key="user_1", value={"name": "Alice"}, collection="users")
user = await store.get(key="user_1", collection="users")
Installation:
Use Cases:
- Applications already using PostgreSQL
- Need for SQL querying on stored data
- ACID transaction requirements
- Complex data relationships
Characteristics:
- JSONB storage for efficient querying
- TTL support via expiration timestamps
- Single table design (collections as column values)
- Async-only (uses asyncpg)
- Stable storage format: Unstable
MemcachedStore¶
High-performance distributed memory caching system.
from key_value.aio.stores.memcached import MemcachedStore
store = MemcachedStore(host="127.0.0.1", port=11211)
Installation:
Use Cases:
- Distributed caching
- Session storage
- High-throughput caching
Characteristics:
- Very fast
- Simple protocol
- Distributed by design
- No persistence
- Stable storage format: Unstable
Choosing a Store¶
Development¶
Recommended: MemoryStore or DiskStore
- Fast iteration
- No setup required
- Easy debugging
Production Caching¶
Recommended: RedisStore or ValkeyStore
- High performance
- Distributed
- Production-ready
- Stable storage format
# Production caching
from key_value.aio.stores.redis import RedisStore
store = RedisStore(url="redis://localhost:6379/0")
Long-Term Storage¶
Recommended: Stores with Stable stability rating
RedisStoreValkeyStoreDiskStoreMultiDiskStoreKeyringStore
Avoid unstable stores for data you can't afford to lose or migrate.
Sensitive Data¶
Recommended: KeyringStore or VaultStore
- OS-level encryption
- Secure by default
- Audit logging (Vault)
# Sensitive data
from key_value.aio.stores.keyring import KeyringStore
store = KeyringStore(service_name="my-app")
Serverless/Cloud¶
Recommended: DynamoDBStore (AWS)
- Fully managed
- Auto-scaling
- No servers to maintain
# AWS Lambda
from key_value.aio.stores.dynamodb import DynamoDBStore
store = DynamoDBStore(table_name="kv-store", region_name="us-east-1")
Store Compatibility¶
All stores implement the same protocol, making it easy to switch:
# Development
store = MemoryStore()
# Production
store = RedisStore(url="redis://localhost:6379/0")
# Your code works with both!
await store.put(key="user:123", value={"name": "Alice"}, collection="users")
See the API Reference for complete store documentation.