Drivers
AIOpen as plain markdown for AIDepending on your use-case storage and performance requirements, you can use different drivers.
Memory
Mainly useful when you want fast access for limited amount of cached data. Use this driver for high-frequency RPC calls.
database: evmJsonRpcCache: connectors: - id: memory-cache driver: memory memory: maxItems: 10000 maxTotalSize: '1GB' # For debugging purposes, enable metrics collection (expect 10% performance hit) emitMetrics: false policies: - network: '*' method: '*' finality: finalized connector: memory-cacheRedis
Redis is useful when you need to store cached data temporarily with eviction policy (e.g. certain amount of memory).
database: evmJsonRpcCache: connectors: - id: redis-cache driver: redis redis: # Connection URI (Required) # Format: redis://[username]:[password]@[host][:port][/database][?dial_timeout=...&pool_size=...] # Example: redis://:some-secret@redis.svc.cluster.local:6379/?pool_size=10 uri: 'redis://username:password@host:port/db?dial_timeout=5s&read_timeout=1s&write_timeout=2s&pool_size=10' tls: enabled: false # or true if redis is configured with TLS certFile: /path/to/client.crt # Optional keyFile: /path/to/client.key # Optional caFile: /path/to/ca.crt # Optional policies: - network: '*' method: '*' finality: finalized connector: redis-cacheTLS options
The tls block uses the shared TLSConfig struct. See TLS configuration for the full field reference.
When your Redis endpoint already uses rediss:// (for example, Railway or Upstash), TLS is negotiated automatically and you can omit the entire tls: block.
Add the tls: section only when you need mutual‑TLS (client certificate/key) or your server uses a private CA:
redis:
uri: rediss://user:pass@redis.internal:6380/0
tls:
enabled: true
certFile: /secrets/redis-client.crt # sent to server (mTLS)
keyFile: /secrets/redis-client.key
caFile: /secrets/redis-rootCA.pem # trust this CA instead of system rootsRedis URI Format
The Redis URI format follows this pattern:
redis://[[username]:[password]@][host][:port][/database][?dial_timeout=value1&read_timeout=value2&write_timeout=value3&pool_size=value4]Examples:
redis://localhost:6379/0- Basic connection to localhostredis://user:pass@redis.example.com:6379/0- Connection with authenticationredis://:password@redis.example.com:6379/0- Connection with password only (no username)redis://redis.example.com:6379- Connection without database number (defaults to 0)redis://redis.example.com:6379/0?dial_timeout=5s&read_timeout=1s&write_timeout=2s&pool_size=10- Connection with timeouts and pool sizeredis://global-shared-states-redis-master.redis.svc.cluster.local:6379- Kubernetes service deployed via Bitnami charts (opens in a new tab)
You can include these parameters directly in the URI:
dial_timeout- Timeout for initial connection (e.g.,5s)read_timeout- Timeout for read operations (e.g.,1s)write_timeout- Timeout for write operations (e.g.,2s)pool_size- Connection pool size (e.g.,10)
Configuration Notes
maxmemory 2000mb
maxmemory-policy allkeys-lruPostgreSQL
Useful when you need to store cached data permanently without TTL i.e. forever.
You don't need to create the table, the driver will automatically create the table and requried indexes.
database: evmJsonRpcCache: connectors: - id: postgres-cache driver: postgresql postgresql: connectionUri: postgres://YOUR_USERNAME_HERE:YOUR_PASSWORD_HERE@your.postgres.hostname.here.com:5432/your_database_name table: rpc_cache initTimeout: 5s getTimeout: 1s setTimeout: 2s policies: - network: '*' method: '*' finality: finalized connector: postgres-cacheDynamoDB
When you need to have scalable (compared to Postgres) permanent caching and are happy with the costs.
database: evmJsonRpcCache: connectors: - id: dynamodb-cache driver: dynamodb dynamodb: table: erpc_json_rpc_cache region: eu-west-1 initTimeout: 5s getTimeout: 1s setTimeout: 2s endpoint: https://dynamodb.eu-west-1.amazonaws.com # Optional # Auth is optional if you are running within AWS. auth: mode: secret # file, or env accessKeyId: YOUR_ACCESS_KEY_ID # Only if mode is secret secretAccessKey: YOUR_SECRET_ACCESS_KEY # Only if mode is secret profile: xxxxx # Only if mode is file credentialsFile: xxxx # Only if mode is file policies: - network: '*' method: '*' finality: finalized connector: dynamodb-cacheIAM Permissions
Make sure the IAM role/user has the necessary permissions to create and/or access the DynamoDB table:
- Table Management:
dynamodb:CreateTable- For creating the table if it doesn't existdynamodb:DescribeTable- For checking table existence and configurationdynamodb:UpdateTable- For adding the global secondary indexdynamodb:UpdateTimeToLive- For configuring TTL attributes
- Data Operations:
dynamodb:PutItem- For storing data and creating locksdynamodb:GetItem- For retrieving data (certain cache queries such as eth_getBlockByNumber with a hex block number)dynamodb:Query- For querying with the reverse index (certain cache queries such as eth_getBlockReceipts by blockHash)dynamodb:DeleteItem- For removing locksdynamodb:UpdateItem- For counter operations with conditions
You can create the table and the reverse GSI index manually and avoid "Table management" permissions:
- Table name:
erpc_json_rpc_cache - Reverse GSI index name:
idx_requestKey_groupKeywith primary keyrequestKeyand sort keygroupKeyand projection typeALL
Copy for your AI assistant — full driver referenceExpand for every option, default, and edge case — or copy this entire section into your AI assistant.
Common connector fields (all drivers)
| Field | Notes |
|---|---|
id | Unique identifier; referenced from policies[].connector. |
driver | One of memory, redis, postgresql, dynamodb. |
failsafeForGets[] | Optional. Failsafe policies (matchMethod, timeout, retry, ...) applied to read operations on this connector. Useful for short-timeout best-effort reads. |
failsafeForSets[] | Optional. Failsafe policies applied to write operations on this connector. Useful for stricter retry on writes. |
memory driver
connectors:
- id: hot
driver: memory
memory:
maxItems: 100000
maxTotalSize: 1GB
emitMetrics: false # default; turning on incurs ~10% performance hit| Field | Default | Notes |
|---|---|---|
maxItems | none | Max entries in the LRU. Either this or maxTotalSize (or both) should be set. |
maxTotalSize | none | Max total cache size (100MB, 1GB). Evicts LRU entries when exceeded. |
emitMetrics | false | Emit per-key hit/miss metrics. ~10% perf hit; intended for debugging. |
redis driver
connectors:
- id: redis-cache
driver: redis
redis:
# Connection — pick ONE of these two ways:
uri: redis://user:pass@host:6379/0?dial_timeout=5s&pool_size=10
# OR explicit fields:
addr: host:6379
username: user
password: pass
db: 0
connPoolSize: 10
# Operation timeouts
initTimeout: 5s
getTimeout: 1s
setTimeout: 2s
# Lock retry interval (for shared-state lock semantics, if used here)
lockRetryInterval: 100ms
# TLS — only needed for mTLS or private CA;
# rediss:// URIs negotiate TLS automatically.
tls:
enabled: true
certFile: /secrets/redis-client.crt
keyFile: /secrets/redis-client.key
caFile: /secrets/redis-rootCA.pem
insecureSkipVerify: false| Field | Notes |
|---|---|
uri | Full Redis URI. When set, takes precedence over individual fields below. URI query-string params (dial_timeout, read_timeout, write_timeout, pool_size) override the equivalent fields. |
addr | Host:port — explicit alternative to uri. |
username, password, db | Auth + database number; alternatives to embedding in uri. |
connPoolSize | Maximum number of TCP connections to keep open. Default 10. |
tls | TLS configuration. See TLS configuration for all fields. |
initTimeout | How long startup waits for the connection to become healthy. |
getTimeout | Timeout for a single GET operation. |
setTimeout | Timeout for a single SET operation. |
lockRetryInterval | Interval between lock-acquisition retries. Applies when this Redis connector backs sharedState or when the cache uses optimistic locking on writes. Default 500ms. |
Recommended Redis server config for cache use cases:
maxmemory 2000mb
maxmemory-policy allkeys-lrupostgresql driver
connectors:
- id: postgres-cache
driver: postgresql
postgresql:
connectionUri: postgres://user:pass@host:5432/erpc
table: rpc_cache
minConns: 2
maxConns: 20
initTimeout: 5s
getTimeout: 1s
setTimeout: 2s| Field | Default | Notes |
|---|---|---|
connectionUri | required | Standard postgres:// URI. Driver creates the table + indexes on first connect; no manual schema work needed. |
table | erpc_json_rpc_cache | Table name. |
minConns | 0 | Minimum connections kept open in the pool. Useful to keep a warm pool ready. |
maxConns | 100 | Maximum connections in the pool. Tune based on your Postgres max_connections. |
initTimeout | 5s | Connection-pool startup timeout. |
getTimeout | 1s | Per-GET timeout. |
setTimeout | 2s | Per-SET timeout. |
PostgreSQL is the recommended permanent-cache backend when you want forever TTLs and operational simplicity.
dynamodb driver
connectors:
- id: dynamodb-cache
driver: dynamodb
dynamodb:
table: erpc_json_rpc_cache
region: eu-west-1
endpoint: https://dynamodb.eu-west-1.amazonaws.com # optional
# Schema attribute overrides (only set these if you provisioned the table manually)
partitionKeyName: requestKey
rangeKeyName: groupKey
reverseIndexName: idx_requestKey_groupKey
ttlAttributeName: ttl
# AWS SDK behavior
maxRetries: 3
# Timing
initTimeout: 5s
getTimeout: 1s
setTimeout: 2s
statePollInterval: 250ms
lockRetryInterval: 100ms
# Auth (optional when running inside AWS with an instance role)
auth:
mode: secret # secret | file | env
accessKeyId: AKIA...
secretAccessKey: ...
# OR for mode: file
profile: erpc-prod
credentialsFile: /home/erpc/.aws/credentials| Field | Default | Notes |
|---|---|---|
table | erpc_json_rpc_cache | Table name. Driver auto-creates if it doesn't exist (requires dynamodb:CreateTable). |
region | required | AWS region. |
endpoint | none | Override the default DynamoDB endpoint. Set when using DynamoDB Local or a regional override. |
auth.mode | uses AWS SDK default chain | secret = use accessKeyId/secretAccessKey; file = read from credentialsFile/profile; env = AWS_* env vars. Omit auth entirely to use the instance-role / IAM-role chain. |
partitionKeyName | requestKey | DynamoDB partition key attribute. Only override if you provisioned the table manually with different schema. |
rangeKeyName | groupKey | Sort/range key attribute. Same caveat. |
reverseIndexName | idx_requestKey_groupKey | Name of the reverse GSI; used for eth_getBlockReceipts and similar block-hash → block-number lookups. |
ttlAttributeName | ttl | TTL attribute name. eRPC writes Unix epoch (seconds) values into this attribute and DynamoDB sweeps expired rows. |
maxRetries | 3 | Max retries for transient AWS errors (throttling, 5xx). |
statePollInterval | 5s | How often the DynamoDB connector polls for counter-value updates when watching shared-state keys (e.g. latest/finalized block numbers). |
lockRetryInterval | 100ms | Backoff between lock-acquisition attempts. |
initTimeout | Startup timeout. | |
getTimeout | Per-GET timeout. | |
setTimeout | Per-SET timeout. |
auth sub-config (DynamoDB and other AWS-backed clients)
| Field | Notes |
|---|---|
mode | secret, file, or env. Determines how credentials are sourced. |
accessKeyID | When mode: secret. |
secretAccessKey | When mode: secret. Redacted in erpc_config output. |
profile | When mode: file. AWS shared-credentials profile name. |
credentialsFile | When mode: file. Path to the credentials file. |
Omit the auth block entirely to use the AWS SDK's default credentials chain (instance role → IRSA → env vars → shared file). This is the recommended path for production deployments.
IAM permissions (DynamoDB)
| Operation | Permission |
|---|---|
| Table management | dynamodb:CreateTable, dynamodb:DescribeTable, dynamodb:UpdateTable, dynamodb:UpdateTimeToLive |
| Data ops | dynamodb:PutItem, dynamodb:GetItem, dynamodb:Query, dynamodb:DeleteItem, dynamodb:UpdateItem |
You can skip table-management permissions by provisioning the table manually:
- Table name matches
dynamodb.table(defaulterpc_json_rpc_cache) - Reverse GSI with name matching
reverseIndexName(defaultidx_requestKey_groupKey), partition keyrequestKey, sort keygroupKey, projection typeALL - TTL enabled on attribute matching
ttlAttributeName(defaultttl)
Per-connector failsafe (read vs write asymmetry)
connectors:
- id: remote-redis
driver: redis
redis: { uri: redis://... }
failsafeForGets: # reads are best-effort: short timeout, no retry
- matchMethod: "*"
timeout: { duration: 50ms }
failsafeForSets: # writes can wait longer + retry
- matchMethod: "*"
timeout: { duration: 500ms }
retry: { maxAttempts: 2, delay: 100ms }Cache reads being slow shouldn't slow the request path (cache is best-effort fall-through); cache writes can afford longer timeouts because they're async to the response.
Common pitfalls
- Setting both
uriand explicit fields —uriquery-string params win; explicit fields without a counterpart in the URI still apply. Avoid the mix; prefer one source of truth. auth.modemissing — DynamoDB tries the SDK default chain and may fail silently if no chain provides creds. Set explicitauthfor non-AWS environments.- PostgreSQL
maxConnshigher than the server'smax_connections— Postgres rejects new connections once its global limit is hit. SizemaxConnsrelative to your total client fleet. - Memory driver without bounds — set
maxItemsormaxTotalSize(or both). Without either, the cache grows unbounded. emitMetrics: trueon a hot memory connector — adds per-key labels and can balloon/metricscardinality + cost ~10% perf. Only for debugging.