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 |
| chDB | Unstable | Embedded ClickHouse engine with SQL access to stored data |
| FileTree | Stable | 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()
ChDBStore¶
Embedded ClickHouse engine (chDB) with SQL access to your key-value data.
from key_value.aio.stores.chdb import ChDBStore
# In-memory database (default)
store = ChDBStore()
# Persistent database (chDB stores data in a directory)
store = ChDBStore(database_path="./my_store.chdb")
# With an existing chDB session
from chdb.session import Session
session = Session("./my_store.chdb")
store = ChDBStore(session=session)
Installation:
Use Cases:
- Analytics on stored key-value data with full ClickHouse SQL
- Embedded OLAP workloads alongside cache-style usage
- Applications needing both key-value access and ClickHouse functions
Characteristics:
- Embedded ClickHouse — no external server required
- In-memory or persistent storage (single directory)
- Process-global singleton: only one
database_pathactive per process at a time - Full ClickHouse SQL on stored data
- ReplacingMergeTree-backed schema (latest write wins via
FINAL) - Synchronous I/O (chDB has no async API; operations block the event loop)
- Expired entries are not automatically culled — see class docstring for cleanup guidance
- Stable storage format: Unstable
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 |
| Azure Tables | Unstable | Azure Table Storage key-value storage |
| 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")
tls_store = RedisStore(
url="rediss://redis.example.com:6380/0",
ssl_ca_certs="/etc/ssl/certs/redis-ca.pem",
)
Redis TLS can be enabled with a rediss:// URL or with ssl=True when using
host and port. Pass ssl_ca_certs to verify the server certificate, and
ssl_certfile plus ssl_keyfile for mutual TLS deployments. For development
or test environments with self-signed certificates, ssl_cert_reqs="none" and
ssl_check_hostname=False are available, but should not be used for production.
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
- SSL/TLS and mutual TLS connection options
- 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)
For Valkey Cluster deployments, pass a GLIDE cluster configuration. The store
will create the GlideClusterClient lazily on first use, so applications can
configure the store before an async event loop is running:
from glide_shared.config import GlideClusterClientConfiguration, NodeAddress
from key_value.aio.stores.valkey import ValkeyStore
cluster_store = ValkeyStore(
config=GlideClusterClientConfiguration(
addresses=[NodeAddress("valkey-cluster.example.com", 6379)]
)
)
Installation:
Use Cases:
- Same as Redis
- Open-source preference
- Redis API compatibility
Characteristics:
- Redis-compatible
- Open-source governance
- Production-ready
- Standalone and cluster-mode GLIDE clients
- Stable storage format
FirestoreStore¶
Google Cloud Firestore used as a key-value store.
from key_value.aio.stores.firestore import (
FirestoreStore,
FirestoreV1CollectionSanitizationStrategy,
FirestoreV1KeySanitizationStrategy,
)
store = FirestoreStore(
credentials=google_credentials,
database="firestore-db",
key_sanitization_strategy=FirestoreV1KeySanitizationStrategy(),
collection_sanitization_strategy=FirestoreV1CollectionSanitizationStrategy(),
)
Installation:
Use Cases:
- Google Cloud-native applications
- Serverless / managed infrastructure
- Existing Firestore deployments
Characteristics:
- Managed cloud database
- Document/collection model
- Optional key and collection sanitization for Firestore ID constraints
- Firestore sanitizers reserve
H_andS_prefixes for keys and collections to prevent collisions - Stable storage format: Unstable
AzureTablesStore¶
Azure Table Storage integration for Azure-native applications.
from key_value.aio.stores.azure_tables import (
AzureTablesSanitizationStrategy,
AzureTablesStore,
)
store = AzureTablesStore(
account_name="mystorageaccount",
credential=credential,
table_name="kvstore",
collection_sanitization_strategy=AzureTablesSanitizationStrategy(),
key_sanitization_strategy=AzureTablesSanitizationStrategy(),
)
Installation:
Use Cases:
- Azure-native applications
- Serverless / managed infrastructure
- Low-cost persistent state
- Managed Identity authentication
- OAuth/session state on Azure Container Apps
Characteristics:
- Fully managed
- Pay-per-use pricing
- No native background TTL; entries are lazily expired on read
- Optional PartitionKey/RowKey sanitization for Azure Tables limits
- 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.