EDXRedis Function

Redis integration for real-time data enrichment, caching, and storage operations in Edge Delta pipelines.

Overview

Redis is an open-source, in-memory data structure store that serves as a database, cache, message broker, and streaming engine. It supports diverse data structures including strings, hashes, lists, sets, sorted sets, bitmaps, hyperloglogs, and geospatial indexes. With sub-millisecond latency and support for millions of operations per second, Redis excels at real-time use cases such as session caching, rate limiting, leaderboards, and distributed locks, making it the de facto standard for high-performance data operations in modern architectures.

The EDXRedis function brings Redis’s power directly into Edge Delta’s OTTL pipelines as a converter function, enabling real-time data enrichment, caching, and stateful processing of telemetry data. By integrating with Redis, pipelines can perform dynamic lookups to enrich logs with user metadata, implement deduplication to track unique events, maintain rolling counters for rate limiting, and correlate distributed traces across services. The function returns results from any Redis command and supports all deployment modes including Standalone for simplicity, Cluster for horizontal scaling across multiple nodes, and Sentinel for automatic failover and high availability, ensuring your enrichment layer scales seamlessly with your telemetry volume.

Minimum Agent Version: v2.5.0

Key Features

  • Support for Redis Standalone, Cluster, and Sentinel deployments
  • Universal command support - executes any valid Redis command
  • Batch operations for performance optimization
  • Automatic connection pooling and reuse
  • Full TLS/mTLS support with certificate validation
  • Client-side caching support
  • Thread-safe client management

Syntax

EDXRedis(connection_config, commands)

connection_config

The connection_config parameter is a map containing Redis connection details. This configuration object determines how EDXRedis connects to your Redis deployment, including the server URL, authentication method, and TLS settings.

url

Required. The Redis connection string that specifies the server endpoint(s). The format varies based on your deployment type:

  • Standalone: "redis://localhost:6379" or "redis://default:password@host:port"
  • Cluster: "redis://node1:6379,node2:6379,node3:6379"
  • Sentinel: "redis://sentinel1:26379,sentinel2:26379,sentinel3:26379"
  • With TLS: "rediss://host:port" (note the double ’s’ in rediss)

deploymentType

Optional. Specifies the Redis deployment architecture as "Standalone", "Cluster", or "Sentinel". Defaults to "Standalone" if not specified. This setting ensures proper handling of cluster redirects and sentinel failovers.

sentinelMasterName

Required for Sentinel. The name of the Redis master as configured in your Sentinel setup. This parameter is mandatory when using Sentinel deployment type to enable proper master discovery.

auth

Optional. Authentication configuration for password-protected Redis instances. Currently supports only the "Manual" method with the following fields:

  • method: Must be "Manual" (Note: UserSecret method is not yet implemented)
  • username: Redis username for ACL-based authentication
  • password: Redis password for authentication

tls

Optional. TLS/SSL configuration for encrypted connections. When enabled, this secures the communication channel between Edge Delta and Redis:

  • enabled: Boolean flag to enable TLS
  • validateCerts: Boolean flag to validate server certificates
  • caCertPath: Path to the CA certificate file for server verification
  • certPath: Path to the client certificate file (required for mTLS)
  • keyPath: Path to the client private key file (required for mTLS)
  • serverName: Server name for TLS verification

Important: Certificates MUST include Subject Alternative Names (SANs) for successful TLS handshakes. Common Name (CN) alone is insufficient and will cause “certificate verify failed” errors. When using mTLS, the Edge Delta deployment scripts create Kubernetes secrets that mount certificates at /certs/. Both agent runtime and platform API configurations assume these certificate files are present at the specified paths.

blockingTimeout

Optional. Timeout for blocking operations in seconds. Defaults to 60 seconds. This applies to blocking commands like BLPOP or BRPOP.

clientSideCache

Optional. Boolean flag to enable client-side caching for improved performance on frequently accessed keys.

options

Optional. A map of additional Redis-specific options as key-value pairs for advanced configurations.

commands

The commands parameter is an array of command objects that specify the Redis operations to execute. Each command object in the array contains the following fields:

outField

Required. The field name where the command result will be stored. This is mandatory for all commands and determines how you access the result in subsequent pipeline statements.

command

Required. The Redis command name to execute (case-insensitive). Any valid Redis command can be used, such as GET, SET, HGET, INCR, etc.

key

Optional. The Redis key to operate on. Required for most commands except server commands like PING or INFO.

args

Optional. An array of additional arguments specific to the command. For example, SET command might include expiration time, HGET requires the field name, etc.

Important: The outField parameter is mandatory for EDXRedis to return results. Without it, operations may execute but results will not be accessible in your pipeline.

Supported Redis Commands

EDXRedis supports all Redis commands through a generic command interface. Any valid Redis command can be executed.

Category Commands Description
String Operations GET, SET, SETEX, SETNX Basic string get/set operations with optional expiration and conditional setting
MGET, MSET Multiple key operations for batch get/set
INCR, INCRBY, DECR, DECRBY Atomic increment/decrement operations for counters
APPEND, STRLEN String manipulation - append content and get length
GETSET, GETRANGE, SETRANGE Advanced string operations - atomic get+set, substring operations
Key Management EXISTS, DEL Check key existence and delete keys
EXPIRE, EXPIREAT, TTL, PTTL Set and query key expiration times
PERSIST, RENAME, RENAMENX Remove expiration, rename keys (with conditional rename)
TYPE, KEYS, SCAN, RANDOMKEY Key inspection, pattern matching, and iteration
List Operations LPUSH, RPUSH, LPOP, RPOP Add/remove elements from list heads and tails
LLEN, LRANGE, LINDEX Get list length, range of elements, or element at index
LSET, LTRIM, LREM, LINSERT Modify lists - set by index, trim, remove, or insert elements
Set Operations SADD, SREM Add/remove members from sets
SISMEMBER, SMEMBERS Check membership and get all members
SCARD, SPOP, SRANDMEMBER Get set size, pop random member, or get random member
SUNION, SINTER, SDIFF Set operations - union, intersection, and difference
Hash Operations HSET, HGET, HMGET Set/get hash fields (single or multiple)
HGETALL, HKEYS, HVALS Get all fields+values, all keys, or all values
HDEL, HEXISTS Delete fields and check field existence
HLEN, HINCRBY, HSETNX Get hash size, increment field, conditional set
Sorted Set Operations ZADD, ZREM Add/remove members with scores
ZSCORE, ZRANK Get member score or rank
ZRANGE, ZRANGEBYSCORE Get members by rank or score range
ZCOUNT, ZCARD, ZINCRBY Count members, get size, increment scores

Examples

Simple GET Operation

This example retrieves a value from Redis using the GET command, which fetches the string value associated with a given key.

Consider this log:

{
  "timestamp": "2025-09-18T10:30:45Z",
  "level": "INFO",
  "message": "User login attempt",
  "event_id": "evt_001",
  "user_id": "user_1"
}

Assume it is passed through the Edge Delta pipeline with this configuration:

- name: redis_get
  type: ottl_transform
  statements: |-
    set(cache["cmd"], [{"command": "get", "key": "user:123", "outField": "user_data"}])
    set(cache["result"], EDXRedis({"url": "redis://localhost:6379"}, cache["cmd"]))
    set(attributes["user"], cache["result"]["user_data"]) where cache["result"]["user_data"] != nil    

In this processor, the first statement creates a Redis GET command for the key “user:123” and stores it in the cache. The second statement executes this command against Redis at localhost:6379 and stores the full response. The third statement extracts the user data from the result and adds it as an attribute, but only if the value is not nil.

The following output log would be generated (assuming Redis key “user:123” contains “John Doe”):

{
  "timestamp": "2025-09-18T10:30:45Z",
  "level": "INFO",
  "message": "User login attempt",
  "event_id": "evt_001",
  "user_id": "user_1",
  "attributes": {
    "user": "John Doe"
  }
}

In the output, the user attribute has been added with the value “John Doe” that was retrieved from Redis, enriching the original log with additional context about the user.

Note: If the key doesn’t exist in Redis, the user attribute will not be added due to the where condition checking for nil.

SET with Expiration

This example stores a value in Redis with an expiration time using the SET command with the EX (expire in seconds) option.

Consider this log:

{
  "timestamp": "2025-09-18T04:00:00Z",
  "sequence": 1,
  "event_id": "evt_001",
  "user_id": "user_1",
  "action": "test_action",
  "data": "test_data_1"
}

Assume it is passed through the Edge Delta pipeline with this configuration:

- name: redis_set_with_ttl
  type: ottl_transform
  statements: |-
    set(cache["value"], String(attributes["data"]))
    set(cache["cmd"], [{"command": "set", "key": "temp:data", "args": [cache["value"], "EX", "60"], "outField": "result"}])
    set(cache["response"], EDXRedis({"url": "redis://localhost:6379"}, cache["cmd"]))
    set(attributes["redis.set.result"], cache["response"]["result"])    

In this processor, the first statement converts the data attribute to a string. The second statement creates a Redis SET command with a 60-second expiration time. The third statement executes the command against Redis. The fourth statement adds the operation result as an attribute.

The following output log would be generated:

{
  "timestamp": "2025-09-18T04:00:00Z",
  "sequence": 1,
  "event_id": "evt_001",
  "user_id": "user_1",
  "action": "test_action",
  "data": "test_data_1",
  "attributes": {
    "redis.set.result": "OK"
  }
}

In the output, the redis.set.result attribute contains “OK”, confirming that the value was successfully stored in Redis with a 60-second TTL. The key “temp:data” now contains “test_data_1” and will automatically expire after 60 seconds.

Note: The SET command returns “OK” when successful. You can verify the TTL using the TTL command, which would return the remaining seconds (e.g., 59 if checked immediately after setting).

Manual Authentication

This example demonstrates connecting to a password-protected Redis instance using manual authentication credentials.

Consider this log:

{
  "timestamp": "2025-09-18T06:30:00Z",
  "level": "INFO",
  "message": "Secure data access request",
  "request_id": "req_456",
  "user": "admin"
}

Assume it is passed through the Edge Delta pipeline with this configuration:

- name: redis_with_auth
  type: ottl_transform
  statements: |-
    set(cache["config"], {"url": "redis://redis-auth.test-destination.svc.cluster.local:6379", "auth": {"method": "Manual", "username": "myuser", "password": "mypassword"}})
    set(cache["cmd"], [{"command": "get", "key": "secure:data", "outField": "data"}])
    set(cache["result"], EDXRedis(cache["config"], cache["cmd"]))
    set(attributes["secure_value"], cache["result"]["data"]) where cache["result"]["data"] != nil    

In this processor, the first statement creates a configuration object with Redis connection details including manual authentication. The second statement prepares a GET command for the key “secure:data”. The third statement executes the authenticated command against Redis. The fourth statement adds the retrieved value as an attribute if it exists.

The following output log would be generated (assuming Redis key “secure:data” contains “confidential_info”):

{
  "timestamp": "2025-09-18T06:30:00Z",
  "level": "INFO",
  "message": "Secure data access request",
  "request_id": "req_456",
  "user": "admin",
  "attributes": {
    "secure_value": "confidential_info"
  }
}

In the output, the secure_value attribute contains the data retrieved from the authenticated Redis instance, demonstrating successful authentication and data retrieval.

Note: Manual authentication is currently the only supported authentication method. The UserSecret method is not yet implemented and will return an error if attempted.

TLS Configuration

This example shows the configuration for connecting to Redis over TLS using server certificate validation.

Consider this log:

{
  "timestamp": "2025-09-18T08:45:00Z",
  "level": "INFO",
  "message": "Encrypted channel request",
  "transaction_id": "txn_789",
  "service": "payment"
}

The following configuration is intended for TLS connections:

- name: redis_with_tls
  type: ottl_transform
  statements: |-
    set(cache["config"], {"url": "rediss://redis-tls.test-destination.svc.cluster.local:6379", "tls": {"enabled": true, "validateCerts": true, "caCertPath": "/certs/ca.crt"}})
    set(cache["cmd"], [{"command": "get", "key": "secure:config", "outField": "config_data"}])
    set(cache["result"], EDXRedis(cache["config"], cache["cmd"]))
    set(attributes["config"], cache["result"]["config_data"]) where cache["result"]["config_data"] != nil    

Important Note: During testing (September 2025), this TLS-only configuration exhibited silent failures with no TLS handshake attempts or data retrieval. The issue appears related to certificate validation requirements. For production use, we recommend using the mTLS configuration (Example 4b) which has been thoroughly validated, or ensure your server certificate includes proper Subject Alternative Names (SANs) that match the hostname used in the connection URL.

Known Requirements:

  • Server certificate MUST include Subject Alternative Names (SANs)
  • The SAN must match the hostname in the connection URL
  • Common Name (CN) alone is insufficient and will cause connection failures

For a working encrypted connection, see Example 4b (mTLS) which has been validated in production environments.

mTLS Configuration (Mutual TLS)

This example demonstrates mutual TLS authentication where both the client and server validate each other’s certificates.

Consider this log:

{
  "level": "INFO",
  "message": "Test log from telemetry generator",
  "test_id": "11526",
  "timestamp": "2025-09-19T00:31:09+00:00"
}

Assume it is passed through the Edge Delta pipeline with this configuration:

- name: redis_with_mtls
  type: ottl_transform
  statements: |-
    # Configure mTLS connection with client certificates
    set(cache["config"], {
      "url": "rediss://redis-mtls.test-destination.svc.cluster.local:6379",
      "tls": {
        "enabled": true,
        "validateCerts": true,
        "caCertPath": "/certs/ca.crt",
        "certPath": "/certs/client.crt",
        "keyPath": "/certs/client.key"
      }
    })

    # Test connection with PING
    set(cache["ping_cmd"], [{"command": "ping", "outField": "ping_result"}])
    set(cache["ping_result"], EDXRedis(cache["config"], cache["ping_cmd"]))
    set(attributes["redis.mtls.ping"], cache["ping_result"]["ping_result"])

    # SET operation over mTLS
    set(cache["set_cmd"], [{"command": "set", "key": "secure:key", "args": ["secure_data"], "outField": "set_result"}])
    set(cache["set_result"], EDXRedis(cache["config"], cache["set_cmd"]))
    set(attributes["redis.mtls.set"], cache["set_result"]["set_result"])

    # GET operation over mTLS
    set(cache["get_cmd"], [{"command": "get", "key": "secure:key", "outField": "get_result"}])
    set(cache["get_result"], EDXRedis(cache["config"], cache["get_cmd"]))
    set(attributes["redis.mtls.get"], cache["get_result"]["get_result"])    

In this processor, the first statement creates a complete mTLS configuration with CA certificate for server validation and client certificate/key for client authentication. The subsequent statements execute PING to verify connectivity, SET to store data, and GET to retrieve it, all over the mutually authenticated TLS connection.

The following output log would be generated:

{
  "level": "INFO",
  "message": "Test log from telemetry generator",
  "test_id": "11526",
  "timestamp": "2025-09-19T00:31:09+00:00",
  "attributes": {
    "redis.mtls.ping": "PONG",
    "redis.mtls.set": "OK",
    "redis.mtls.get": "secure_data"
  }
}

In the output, the redis.mtls.ping confirms connectivity with “PONG”, redis.mtls.set shows successful storage with “OK”, and redis.mtls.get contains the retrieved value “secure_data”, all demonstrating successful mutual TLS authentication and encrypted operations.

Critical Requirements:

  • Both server and client certificates MUST include Subject Alternative Names (SANs)
  • The Edge Delta deployment automatically mounts certificates at /certs/ from Kubernetes secrets
  • Ensure the same CA signs both server and client certificates for successful mutual authentication

Batch Operations

This example demonstrates executing multiple Redis commands in a single call for improved performance.

Consider this log:

{
  "timestamp": "2025-09-18T10:45:00Z",
  "level": "INFO",
  "message": "Application status check",
  "service": "monitoring",
  "check_id": "chk_123"
}

Assume it is passed through the Edge Delta pipeline with this configuration:

- name: batch_operations
  type: ottl_transform
  statements: |-
    # Execute multiple commands in one call
    set(cache["cmds"], [
      {"command": "get", "key": "config:app", "outField": "app_config"},
      {"command": "incr", "key": "counters:requests", "outField": "request_count"},
      {"command": "hget", "key": "server:status", "args": ["health"], "outField": "health"}
    ])
    set(cache["results"], EDXRedis({"url": "redis://localhost:6379"}, cache["cmds"]))

    # Access individual results
    set(attributes["app_config"], cache["results"]["app_config"]) where cache["results"]["app_config"] != nil
    set(attributes["requests"], cache["results"]["request_count"]) where cache["results"]["request_count"] != nil
    set(attributes["health"], cache["results"]["health"]) where cache["results"]["health"] != nil    

In this processor, the first statement creates an array of three Redis commands: GET to retrieve configuration, INCR to increment a counter, and HGET to fetch a hash field. The second statement executes all three commands in a single EDXRedis call. The remaining statements extract each result and add them as attributes.

The following output log would be generated (assuming the keys exist with appropriate values):

{
  "timestamp": "2025-09-18T10:45:00Z",
  "level": "INFO",
  "message": "Application status check",
  "service": "monitoring",
  "check_id": "chk_123",
  "attributes": {
    "app_config": "production_v2.1",
    "requests": 1250,
    "health": "healthy"
  }
}

In the output, three attributes are added from the batch operation: app_config contains the configuration string, requests shows the incremented counter value, and health displays the status from the hash.

Performance Note: Batch operations reduce network round trips by sending multiple commands together. This is particularly beneficial when enriching logs with multiple Redis lookups or when performing related operations that can be grouped.

Hash Operations

This example demonstrates storing and retrieving multiple fields in a Redis hash structure.

Consider this log:

{
  "timestamp": "2025-09-18T05:32:52+00:00",
  "sequence": 20298,
  "server_id": "srv_0",
  "metrics": {"cpu": 45, "memory": 78, "disk": 62},
  "status": "active"
}

Assume it is passed through the Edge Delta pipeline with this configuration:

- name: hash_operations
  type: ottl_transform
  statements: |-
    # Store multiple fields in a hash
    set(cache["cmd"], [{"command": "hset", "key": "server:metrics", "args": ["cpu", "45", "memory", "78", "disk", "62"], "outField": "fields_added"}])
    set(cache["result"], EDXRedis({"url": "redis://localhost:6379"}, cache["cmd"]))
    set(attributes["fields_stored"], cache["result"]["fields_added"])

    # Retrieve all hash fields
    set(cache["get_cmd"], [{"command": "hgetall", "key": "server:metrics", "outField": "metrics"}])
    set(cache["metrics"], EDXRedis({"url": "redis://localhost:6379"}, cache["get_cmd"]))
    set(attributes["server_metrics"], cache["metrics"]["metrics"])    

In this processor, the first statement creates an HSET command to store three field-value pairs in a hash. The second statement executes the command. The third statement captures the number of fields added. The fourth statement prepares an HGETALL command to retrieve all fields. The fifth statement executes the retrieval. The sixth statement adds the metrics as an attribute.

The following output log would be generated:

{
  "timestamp": "2025-09-18T05:32:52+00:00",
  "sequence": 20298,
  "server_id": "srv_0",
  "metrics": {"cpu": 45, "memory": 78, "disk": 62},
  "status": "active",
  "attributes": {
    "fields_stored": 3,
    "server_metrics": ["cpu", "45", "memory", "78", "disk", "62"]
  }
}

In the output, fields_stored shows that 3 fields were added to the hash, and server_metrics contains the retrieved data as a flat array in Redis format [key1, value1, key2, value2…].

Important Note: HGETALL returns data as a flat array rather than a map/object. To work with individual fields, consider using HGET commands for specific fields or post-process the array in OTTL to convert it to a map structure.

Deduplication Pattern

This example demonstrates using SETNX (SET if Not eXists) to detect and prevent duplicate event processing.

Common Use Cases:

  • Use SETNX for exactly-once semantics
  • Track processed event IDs with TTL
  • Implement idempotency keys
  • Maintain processing history

Consider this log:

{
  "timestamp": "2025-09-18T11:00:00Z",
  "level": "INFO",
  "message": "Payment processed",
  "event_id": "evt_12345",
  "amount": 99.99,
  "user_id": "user_789"
}

Assume it is passed through the Edge Delta pipeline with this configuration:

- name: event_deduplication
  type: ottl_transform
  statements: |-
    # Create unique event key
    set(cache["event_key"], Concat(["event:", attributes["event_id"]], ""))

    # Use SETNX to detect duplicates (returns 1 if new, 0 if exists)
    set(cache["cmd"], [{"command": "setnx", "key": cache["event_key"], "args": ["1"], "outField": "is_new"}])
    set(cache["result"], EDXRedis({"url": "redis://localhost:6379"}, cache["cmd"]))

    # Set TTL on new events (expire after 1 hour)
    set(cache["expire_cmd"], [{"command": "expire", "key": cache["event_key"], "args": ["3600"], "outField": "expire_result"}]) where cache["result"]["is_new"] == 1
    set(cache["expire_result"], EDXRedis({"url": "redis://localhost:6379"}, cache["expire_cmd"])) where cache["result"]["is_new"] == 1

    # Mark as duplicate or new
    set(attributes["is_duplicate"], cache["result"]["is_new"] == 0)
    set(attributes["dedup_key"], cache["event_key"])    

In this processor, the first statement creates a unique key from the event ID. The second and third statements use SETNX to atomically check and set the key. The fourth and fifth statements set an expiration time only for new events. The final statements add attributes indicating whether this is a duplicate.

First occurrence output (new event):

{
  "timestamp": "2025-09-18T11:00:00Z",
  "level": "INFO",
  "message": "Payment processed",
  "event_id": "evt_12345",
  "amount": 99.99,
  "user_id": "user_789",
  "attributes": {
    "is_duplicate": false,
    "dedup_key": "event:evt_12345"
  }
}

Subsequent occurrence output (duplicate within 1 hour):

{
  "timestamp": "2025-09-18T11:05:00Z",
  "level": "INFO",
  "message": "Payment processed",
  "event_id": "evt_12345",
  "amount": 99.99,
  "user_id": "user_789",
  "attributes": {
    "is_duplicate": true,
    "dedup_key": "event:evt_12345"
  }
}

In the output, is_duplicate is false for the first occurrence (SETNX returned 1) and true for any duplicates within the TTL window (SETNX returned 0).

Note: This pattern provides exactly-once semantics within the TTL window. The EXPIRE command ensures automatic cleanup of deduplication keys to prevent memory growth.

CMDB Enrichment

Common Use Cases:

  • Store asset information from ServiceNow, Jira Assets, or custom CMDBs
  • Perform priority-based lookups (asset tag → hostname → IP)
  • Cache enrichment data with appropriate TTLs
  • Track enrichment success rates
- name: cmdb_enrichment
  type: ottl_transform
  statements: |-
    # Extract identifiers
    set(cache["asset_tag"], EDXExtractPatterns(body, "asset_tag=(?P<tag>[A-Z0-9-]+)")["tag"])
    set(cache["hostname"], EDXExtractPatterns(body, "host=(?P<host>[\\w\\.-]+)")["host"])
    # Batch lookup multiple keys
    set(cache["cmds"], [{"command": "get", "key": Concat(["cmdb:asset:", cache["asset_tag"]], ""), "outField": "by_asset"}, {"command": "get", "key": Concat(["cmdb:host:", cache["hostname"]], ""), "outField": "by_host"}])
    set(cache["lookups"], EDXRedis({"url": "redis://localhost:6379"}, cache["cmds"]))
    # Use first available match
    set(cache["cmdb_data"], cache["lookups"]["by_asset"]) where cache["lookups"]["by_asset"] != nil
    set(cache["cmdb_data"], cache["lookups"]["by_host"]) where cache["cmdb_data"] == nil and cache["lookups"]["by_host"] != nil
    # Parse and enrich
    set(cache["cmdb"], ParseJSON(cache["cmdb_data"])) where cache["cmdb_data"] != nil
    merge_maps(attributes, cache["cmdb"], "insert") where cache["cmdb"] != nil    

Redis Cluster

- name: cluster_operation
  type: ottl_transform
  statements: |-
    set(cache["config"], {"url": "redis://node1:6379,node2:6379,node3:6379", "deploymentType": "Cluster"})
    set(cache["cmd"], [{"command": "get", "key": "distributed:data", "outField": "data"}])
    set(cache["result"], EDXRedis(cache["config"], cache["cmd"]))    

Redis Sentinel

- name: sentinel_operation
  type: ottl_transform
  statements: |-
    set(cache["config"], {"url": "redis://sentinel1:26379,sentinel2:26379", "deploymentType": "Sentinel", "sentinelMasterName": "mymaster"})
    set(cache["cmd"], [{"command": "get", "key": "ha:data", "outField": "data"}])
    set(cache["result"], EDXRedis(cache["config"], cache["cmd"]))    

Error Handling

Nil Responses

- name: handle_nil
  type: ottl_transform
  statements: |-
    set(cache["cmd"], [{"command": "get", "key": "missing:key", "outField": "data"}])
    set(cache["result"], EDXRedis({"url": "redis://localhost:6379"}, cache["cmd"]))
    # Nil is normal for non-existent keys
    set(attributes["data"], cache["result"]["data"]) where cache["result"]["data"] != nil
    set(attributes["data"], "default_value") where cache["result"]["data"] == nil    

Connection Failures

- name: handle_failure
  type: ottl_transform
  statements: |-
    set(cache["result"], EDXRedis({"url": "redis://localhost:6379"}, cache["cmd"]))
    # Connection errors are logged but don't stop the pipeline
    set(attributes["source"], "redis") where cache["result"] != nil
    set(attributes["source"], "fallback") where cache["result"] == nil    

Performance Optimization

Connection Pooling

The EDXRedis function automatically manages a connection pool:

  • Clients are cached and reused based on connection configuration
  • Connection configurations are hashed for efficient lookups
  • Unhealthy clients are automatically detected and replaced
  • Memory-efficient sharing of client instances

Batch Operations

Execute multiple commands in a single call to reduce round trips:

set(cache["cmds"], [{"command": "get", "key": "k1", "outField": "v1"}, {"command": "get", "key": "k2", "outField": "v2"}, {"command": "get", "key": "k3", "outField": "v3"}])
set(cache["results"], EDXRedis(config, cache["cmds"]))

Key Design Best Practices

  • Use consistent key naming: namespace:type:id
  • Keep keys short but descriptive
  • Use hash tags for cluster slot control: {user:123}:session
  • Implement key expiration strategy

Troubleshooting

For a comprehensive troubleshooting guide with detailed solutions, see the EDXRedis Troubleshooting Guide.

Common Issues

Issue Cause Solution
No results returned Missing outField Always include outField in command objects
Connection refused Wrong host/port Verify Redis is running and accessible
AUTH failed Invalid credentials Check username/password with Manual auth method
TLS handshake failed Certificate issues Ensure certificates include SANs; verify CA cert path and server name
“certificate verify failed” Missing SANs in certificates Regenerate certificates with proper Subject Alternative Names
Cluster redirect Wrong deployment type Set deploymentType: "Cluster" for Redis Cluster
Sentinel can’t find master Wrong master name Verify sentinelMasterName matches Sentinel config
High latency Network or blocking timeout Adjust blockingTimeout parameter
Memory errors Redis full Implement eviction policy or increase memory

Debug Techniques

- name: debug_redis
  type: ottl_transform
  statements: |-
    # Test connectivity
    set(cache["ping_cmd"], [{"command": "ping", "key": "", "outField": "pong"}])
    set(cache["ping_result"], EDXRedis({"url": "redis://localhost:6379"}, cache["ping_cmd"]))
    set(attributes["redis.connected"], cache["ping_result"]["pong"] == "PONG")
    # Log for debugging
    set(attributes["debug.cmd"], String(cache["cmd"]))
    set(attributes["debug.result"], String(cache["result"]))    

Additional Resources

Edge Delta Documentation

Redis Documentation