Join our community of builders on

Telegram!Telegram

Storage Configuration

Overview

OpenZeppelin Relayer supports two storage backends for persisting configuration data and transaction state. The choice of storage backend affects how configuration is managed, data persistence, and performance characteristics.

Storage type determines how your configuration changes persist and how file-based and API-based configuration interact. Choose the right storage type for your deployment needs.

Community Contributions Welcome: Additional storage backends (such as PostgreSQL, MongoDB, or other databases) are welcomed as contributions from the open source community. The storage system is designed to be extensible, making it straightforward to add new storage implementations.

Storage Types

In-Memory Storage

In-memory storage keeps all configuration and transaction data in the application’s memory.

Use Cases

  • Development and testing environments
  • Temporary deployments
  • Single-instance deployments
  • When data persistence across restarts is not required

Characteristics

  • Fast Performance: No network overhead for data access
  • No External Dependencies: Does not require Redis or other external services
  • No Persistence: All data is lost when the container restarts
  • Single Instance: Cannot be shared across multiple relayer instances

Configuration Sync Behavior

  • Configuration from config.json is loaded on every startup
  • API changes are not synchronized back to config.json file
  • All API-based configuration changes are lost on restart
  • File-based configuration always takes precedence on startup
# Enable in-memory storage
REPOSITORY_STORAGE_TYPE=in-memory

Redis Storage

Redis storage persists all configuration and transaction data in a Redis database.

Use Cases

  • Production deployments
  • Multi-instance deployments
  • When data persistence is required
  • Scalable environments
  • When API-based configuration changes should persist

Characteristics

  • Persistent: Data survives container restarts
  • Network Dependency: Requires Redis connection
  • Encryption: Supports encryption at rest for sensitive data

Configuration Sync Behavior

  • Configuration from config.json is loaded into Redis only once during the first startup
  • Subsequent startups use the configuration stored in Redis
  • API changes are persisted and survive restarts
  • File-based configuration can override Redis by setting RESET_STORAGE_ON_START=true
# Enable Redis storage
REPOSITORY_STORAGE_TYPE=redis
REDIS_URL=redis://localhost:6379
STORAGE_ENCRYPTION_KEY=your-encryption-key-here

Configuration Reference

Core Storage Settings

Environment VariableDefault ValueAccepted ValuesDescription
REPOSITORY_STORAGE_TYPEin-memoryin-memory, redisType of storage backend used for storing configuration and transaction data.
RESET_STORAGE_ON_STARTfalsetrue, falseWhen true, clears all data from storage on startup and reloads from config files. Useful for forcing file-based configuration to override stored data.
TRANSACTION_EXPIRATION_HOURS4numberNumber of hours after which transactions in a final state are automatically removed from storage to prevent storage bloat.

Redis-Specific Settings

Environment VariableDefault ValueAccepted ValuesDescription
REDIS_URLredis://localhost:6379Redis connection stringFull connection URL for the Redis primary instance. Used for all write operations and read operations when REDIS_READER_URL is not set.
REDIS_READER_URL(none)Redis connection stringOptional separate endpoint for read operations. When set, read operations (GET, MGET, etc.) use this endpoint while writes use REDIS_URL. Useful for AWS ElastiCache with read replicas to distribute read load.
REDIS_READER_POOL_MAX_SIZE1000numberOptional separate pool size for reader connections. Useful for read-heavy workloads where more reader connections are beneficial.
REDIS_CONNECTION_TIMEOUT_MS10000number (milliseconds)Maximum time to wait when connecting to Redis before timing out.
REDIS_POOL_MAX_SIZE500numberMaximum number of connections in the Redis connection pool. Adjust based on your Redis instance capacity, workload, and deployment scale.
REDIS_POOL_TIMEOUT_MS10000number (milliseconds)Maximum time to wait for a connection from the pool before timing out. Higher values help handle traffic spikes.
REDIS_KEY_PREFIXoz-relayerstringPrefix added to all Redis keys. Useful for namespacing when sharing Redis with other applications.
STORAGE_ENCRYPTION_KEY``string (base64)Encryption key used to encrypt sensitive data at rest in Redis. Generate using cargo run --example generate_encryption_key.

Security Considerations

Redis Security

When using Redis storage in production:

  • Use encryption at rest: Always set STORAGE_ENCRYPTION_KEY
  • Secure Redis access: Use Redis AUTH, TLS, and network security
  • Network isolation: Deploy Redis in a private network
  • Regular backups: Implement Redis backup strategy
  • Monitor access: Log and monitor Redis access patterns

AWS ElastiCache with Read Replicas

When using AWS ElastiCache with read replicas, you can distribute read load across multiple nodes by configuring separate endpoints:

# AWS ElastiCache configuration with read replicas
REDIS_URL=redis://my-cluster.xxx.cache.amazonaws.com:6379            # Primary endpoint (writes)
REDIS_READER_URL=redis://my-cluster-ro.xxx.cache.amazonaws.com:6379  # Reader endpoint (reads)
REDIS_POOL_MAX_SIZE=200                                              # Connections to primary
REDIS_READER_POOL_MAX_SIZE=500                                       # More connections for reads (optional)

Benefits:

  • Reduced primary load: Read operations are distributed to replica nodes
  • Improved read performance: Multiple replicas can handle concurrent reads
  • Better fault tolerance: Read availability continues even during primary failover
  • Cost efficiency: Smaller primary instance with multiple read replicas

When REDIS_READER_URL is not set:

  • All operations (reads and writes) use REDIS_URL
  • This maintains backward compatibility with single-endpoint configurations
  • Suitable for standalone Redis or when read scaling is not needed

Connection Pool Tuning

Redis connection pooling improves performance and prevents connection exhaustion. Configure pool size based on your Redis instance capacity, workload, and deployment scale.

Factors to consider:

  • Redis instance capacity: Check your Redis instance's maximum connection limit (e.g., ElastiCache small instances support 65,000+ connections)
  • Transaction volume: Higher TPS requires more connections
  • Number of relayers: More active relayers increase concurrent operations
  • Instance count: Divide total connection budget across multiple relayer instances
  • Traffic patterns: Account for traffic spikes and peak loads

Configuration:

REDIS_POOL_MAX_SIZE=500          # Adjust based on instance capacity and workload
REDIS_POOL_TIMEOUT_MS=15000         # Time to wait for available connection

Encryption at Rest

Sensitive configuration data is encrypted before being stored in Redis when STORAGE_ENCRYPTION_KEY is provided.

Encrypted Data Includes:

  • Signer private keys and passphrases
  • Webhook signing keys
  • API keys (when stored in configuration)
  • Other sensitive configuration values

Generate Encryption Key:

# Generate a secure encryption key
cargo run --example generate_encryption_key

# Alternative using OpenSSL
openssl rand -base64 32

Transaction Storage Management

Automatic Cleanup

Transactions are automatically removed from storage after reaching their final state to prevent storage bloat:

# Configure transaction retention (default: 4 hours)
TRANSACTION_EXPIRATION_HOURS=8

Final Transaction States:

  • confirmed - Transaction confirmed on blockchain
  • failed - Transaction failed and will not be retried
  • cancelled - Transaction was cancelled by user
  • expired: - Transaction was expired