Skip to content
Tech

Redis Caching Pattern: Akselerasi API 10x dengan Cache yang Benar

API lambat? Cache dulu. Redis pattern yang bener bisa bikin response time turun drastis. Dibahas praktis dengan konteks Radian Group, engineering, automation,
7 minutes to read
4 bulan lalu
Zainul Fanani
Redis Caching Pattern: Akselerasi API 10x dengan Cache yang Benar
πŸ“… 11 Mar 2026🀍0 πŸ‘ 0 πŸ”— 0

πŸ“Ž Source:redis-caching-pattern.md β€” view on GitHub & star ⭐

⚑ Redis Caching Pattern for Speed

Speed up your OpenClaw automations 20x with Redis caching β€” from 1 second to 50ms! πŸš€


πŸ“Š Cache Flow Architecture

A Incoming Request  B Check Redis Cache
A Incoming Request B Check Redis Cache
}}%% flowchart TD AπŸš€ Incoming Request --> B{πŸ” Check Redis Cache} style A fill:#e1f5fe,stroke:#01579b,stroke-width:2px style B fill:#fff3e0,stroke:#e65100,stroke-width:2px

text
B -->|Cache HIT βœ…| C[⚑ Return Cached Data<br/>~5ms]
B -->|Cache MISS ❌| D[🌐 Fetch from External API<br/>~800ms]
style C fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
style D fill:#ffcdd2,stroke:#c62828,stroke-width:2px

D --> E[πŸ’Ύ Store in Redis<br/>with TTL]
style E fill:#e1bee7,stroke:#6a1b9a,stroke-width:2px

E --> F[πŸ“€ Return Fresh Data]
C --> G[βœ… Client Response]
F --> G
style F fill:#b3e5fc,stroke:#0277bd,stroke-width:2px
style G fill:#a5d6a7,stroke:#388e3c,stroke-width:2px'}

πŸ”„ Cache Lifecycle Sequence

participant C as Client
participant C as Client
}}%% sequenceDiagram participant C as Client participant A as App Script participant R as Redis Cache participant API as External API

text
C->>A: Request Data
A->>R: GET cache:key

alt Cache Exists
    R-->>A: Return cached value
    A-->>C: Response (50ms) ⚑
else Cache Expired/Missing
    R-->>A: nil (miss)
    A->>API: HTTP GET
    API-->>A: JSON Response
    A->>R: SETEX key TTL value
    R-->>A: OK
    A-->>C: Response (1s) 🐒
end'}

🎯 Before vs After

text
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  SPEED COMPARISON                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚  WITHOUT CACHE ❌                    WITH CACHE βœ…          β”‚
β”‚                                                             β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚ Request      β”‚                   β”‚ Request      β”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚         β”‚                                  β”‚                β”‚
β”‚         β–Ό                                  β–Ό                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚ API Call     β”‚  800ms            β”‚ Check Redis  β”‚  5ms   β”‚
β”‚  β”‚ (External)   β”‚                   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚         β”‚                                  β”‚                β”‚
β”‚         β–Ό                                  β–Ό                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚ Parse Data   β”‚  200ms            β”‚ Cache Hit!   β”‚  50ms  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚         β”‚                                  β”‚                β”‚
β”‚         β–Ό                                  β–Ό                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚
β”‚  β”‚ Total: 1s    β”‚                   β”‚ Total: 50ms  β”‚        β”‚
β”‚  β”‚ 😫 Slow      β”‚                   β”‚ πŸš€ 20x Fasterβ”‚        β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Real Numbers


🎯 What You'll Build

text
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              REDIS CACHING ARCHITECTURE                     β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚   YOUR SCRIPT                    REDIS SERVER               β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”           β”‚
β”‚   β”‚              β”‚              β”‚              β”‚           β”‚
β”‚   β”‚ 1. Check     │─────────────▢│ Key exists?  β”‚           β”‚
β”‚   β”‚    Cache     β”‚              β”‚              β”‚           β”‚
β”‚   β”‚              │◀─────────────│ YES β†’ Return β”‚           β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜              β”‚      value   β”‚           β”‚
β”‚          β”‚                      β”‚              β”‚           β”‚
β”‚          β”‚ NO                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚
β”‚          β–Ό                             β–²                    β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                     β”‚                    β”‚
β”‚   β”‚ 2. Fetch fromβ”‚                     β”‚                    β”‚
β”‚   β”‚    External  β”‚                     β”‚                    β”‚
β”‚   β”‚    API       β”‚                     β”‚                    β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜                     β”‚                    β”‚
β”‚          β”‚                             β”‚                    β”‚
β”‚          β–Ό                             β”‚                    β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                     β”‚                    β”‚
β”‚   β”‚ 3. Store in  β”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚   β”‚    Cache     β”‚         (with TTL)                        β”‚
β”‚   β”‚              β”‚                                          β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                          β”‚
β”‚                                                             β”‚
β”‚   TTL = Time To Live (auto-expire)                         β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ Installation

Install Redis

bash
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install redis-server

# macOS
brew install redis

# Start Redis
sudo systemctl start redis    # Linux
brew services start redis     # macOS

# Verify
redis-cli ping
# Should return: PONG

Install Redis Client (Bash)

bash
# redis-cli included with server install
# For scripts, use redis-cli directly

# Test connection
redis-cli set test "hello"
redis-cli get test
# Returns: hello

redis-cli del test

πŸ“‹ Step 1: Create Helper Functions

Save this as ~/scripts/redis-utils.sh:

bash
#!/bin/bash

# =============================================================================
# ⚑ Redis Helper Functions for OpenClaw
# =============================================================================

# Default Redis connection
REDIS_HOST="${REDIS_HOST:-localhost}"
REDIS_PORT="${REDIS_PORT:-6379}"

# =============================================================================
# πŸ”§ CORE FUNCTIONS
# =============================================================================

# Set a key with optional TTL (Time To Live in seconds)
redis_set() {
    local key="$1"
    local value="$2"
    local ttl="${3:-}"
    
    if [ -n "$ttl" ]; then
        redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" setex "$key" "$ttl" "$value" >/dev/null
    else
        redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" set "$key" "$value" >/dev/null
    fi
}

# Get a key value
redis_get() {
    local key="$1"
    redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" get "$key"
}

# Delete a key
redis_delete() {
    local key="$1"
    redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" del "$key" >/dev/null
}

# Check if key exists (returns 1 if exists, 0 if not)
redis_exists() {
    local key="$1"
    redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" exists "$key"
}

# Get TTL of a key (returns seconds remaining, -1 if no TTL, -2 if not exists)
redis_ttl() {
    local key="$1"
    redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" ttl "$key"
}

# List keys matching pattern (default: all)
redis_keys() {
    local pattern="${1:-*}"
    redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" keys "$pattern"
}

# =============================================================================
# 🎯 CONVENIENCE FUNCTIONS
# =============================================================================

# Cache JSON data with TTL
redis_cache_json() {
    local key="$1"
    local json_data="$2"
    local ttl="${3:-300}"  # Default 5 minutes
    
    # Compress JSON to single line
    local compressed
    compressed=$(echo "$json_data" | jq -c . 2>/dev/null || echo "$json_data")
    
    redis_set "$key" "$compressed" "$ttl"
}

# Get and parse cached JSON
redis_get_json() {
    local key="$1"
    local value
    value=$(redis_get "$key")
    
    if [ -n "$value" ] && [ "$value" != "nil" ]; then
        echo "$value" | jq . 2>/dev/null || echo "$value"
    else
        echo "null"
    fi
}

# Cache with automatic expiration for different data types
redis_cache_weather() {
    local location="$1"
    local data="$2"
    # Cache weather for 30 minutes
    redis_cache_json "weather:$location" "$data" 1800
}

redis_cache_price() {
    local item="$1"
    local data="$2"
    # Cache prices for 5 minutes
    redis_cache_json "price:$item" "$data" 300
}

redis_cache_health() {
    local service="$1"
    local data="$2"
    # Cache health for 1 minute
    redis_cache_json "health:$service" "$data" 60
}

redis_cache_session() {
    local session_id="$1"
    local data="$2"
    # Cache sessions for 1 hour
    redis_cache_json "session:$session_id" "$data" 3600
}

# =============================================================================
# πŸ“Š MONITORING FUNCTIONS
# =============================================================================

# Show cache statistics
redis_stats() {
    echo "πŸ“Š Redis Statistics"
    echo "=================="
    
    # Memory usage
    echo -n "Memory Used: "
    redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" info memory | grep "used_memory_human" | cut -d: -f2
    
    # Number of keys
    echo -n "Total Keys: "
    redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" dbsize
    
    # Connected clients
    echo -n "Connected Clients: "
    redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" info clients | grep "connected_clients" | cut -d: -f2
}

# Clear all cache (use with caution!)
redis_flush() {
    echo "⚠️  This will delete ALL cached data!"
    read -p "Type 'yes' to confirm: " confirm
    
    if [ "$confirm" = "yes" ]; then
        redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" flushdb
        echo "βœ… Cache cleared"
    else
        echo "❌ Cancelled"
    fi
}

# Show keys by prefix
redis_list_by_prefix() {
    local prefix="$1"
    echo "πŸ”‘ Keys with prefix '$prefix':"
    redis_keys "${prefix}*" | while read -r key; do
        local ttl
        ttl=$(redis_ttl "$key")
        printf "  %-40s (TTL: %s)\n" "$key" "$ttl"
    done
}

Make it executable:

bash
chmod +x ~/scripts/redis-utils.sh

πŸ“‹ Step 2: Use Cases with Code Examples

Use Case 1: Gold/Price Caching

bash
#!/bin/bash

source ~/scripts/redis-utils.sh

fetch_gold_price() {
    local cache_key="price:gold:xauusd"
    
    # 1. Check cache first
    local cached
    cached=$(redis_get_json "$cache_key")
    
    if [ "$cached" != "null" ]; then
        echo "πŸ’° Cache HIT! Gold price (cached):"
        echo "$cached" | jq -r '.price'
        return 0
    fi
    
    echo "πŸ”„ Cache MISS β€” Fetching from API..."
    
    # 2. Fetch from external API
    local api_response
    api_response=$(curl -s "https://api.goldapi.io/v1/XAU/USD" \
        -H "x-access-token: YOUR_API_KEY")
    
    # 3. Parse and format
    local price
    price=$(echo "$api_response" | jq -r '.price')
    
    local formatted_data
    formatted_data=$(jq -n \
        --arg price "$price" \
        --arg time "$(date -Iseconds)" \
        '{price: $price, timestamp: $time, source: "goldapi"}')
    
    # 4. Store in cache (5 minutes)
    redis_cache_price "gold:xauusd" "$formatted_data"
    
    echo "πŸ’° Gold price (fresh): $price"
    echo "βœ… Cached for 5 minutes"
}

# Run
fetch_gold_price

Use Case 2: Weather Caching

bash
#!/bin/bash

source ~/scripts/redis-utils.sh

fetch_weather() {
    local city="${1:-Jakarta}"
    local cache_key="weather:$city"
    
    # Check cache
    local cached
    cached=$(redis_get_json "$cache_key")
    
    if [ "$cached" != "null" ]; then
        echo "🌀️  Weather for $city (cached):"
        echo "$cached" | jq -r '.condition, .temperature'
        return 0
    fi
    
    echo "πŸ”„ Fetching weather for $city..."
    
    # API call (example)
    local weather_data
    weather_data=$(curl -s "https://api.weather.com/v1/current?city=$city" \
        -H "Authorization: Bearer YOUR_KEY")
    
    # Cache for 30 minutes
    redis_cache_weather "$city" "$weather_data"
    
    echo "🌀️  Weather for $city:"
    echo "$weather_data" | jq -r '.condition, .temperature'
}

fetch_weather "Singapore"

Use Case 3: Health Status Caching

bash
#!/bin/bash

source ~/scripts/redis-utils.sh

check_service_health() {
    local service="$1"
    local url="$2"
    local cache_key="health:$service"
    
    # Check cache first (1 minute TTL)
    local cached
    cached=$(redis_get_json "$cache_key")
    
    if [ "$cached" != "null" ]; then
        local status
        status=$(echo "$cached" | jq -r '.status')
        echo "[$service] $status (cached)"
        return 0
    fi
    
    # Check service
    local start_time end_time duration
    start_time=$(date +%s%N)
    
    if curl -s --max-time 5 "$url" >/dev/null 2>&1; then
        end_time=$(date +%s%N)
        duration=$(( (end_time - start_time) / 1000000 ))
        
        local result
        result=$(jq -n \
            --arg status "UP" \
            --argjson response_time "$duration" \
            --arg checked_at "$(date -Iseconds)" \
            '{status: $status, response_time: $response_time, checked_at: $checked_at}')
        
        redis_cache_health "$service" "$result"
        echo "[$service] UP (${duration}ms)"
    else
        local result
        result=$(jq -n \
            --arg status "DOWN" \
            --arg checked_at "$(date -Iseconds)" \
            '{status: $status, checked_at: $checked_at}')
        
        redis_cache_health "$service" "$result"
        echo "[$service] DOWN"
    fi
}

# Check multiple services
echo "πŸ₯ Health Check (with caching):"
check_service_health "api" "https://api.example.com/health"
check_service_health "database" "https://db.example.com/ping"
check_service_health "website" "https://example.com"

Use Case 4: Session Caching

bash
#!/bin/bash

source ~/scripts/redis-utils.sh

# Store user session
save_session() {
    local session_id="$1"
    local user_data="$2"
    
    redis_cache_session "$session_id" "$user_data"
    echo "βœ… Session saved (1 hour)"
}

# Retrieve user session
get_session() {
    local session_id="$1"
    local session_data
    
    session_data=$(redis_get_json "session:$session_id")
    
    if [ "$session_data" != "null" ]; then
        echo "$session_data"
    else
        echo "{}"
    fi
}

# Example usage
user_session='{"user_id": "123", "name": "Alex", "preferences": {"theme": "dark"}}'
save_session "sess_abc123" "$user_session"

retrieved=$(get_session "sess_abc123")
echo "User: $(echo "$retrieved" | jq -r '.name')"

πŸ“‹ Step 3: Complete Working Example

Save this as ~/scripts/cached-api-call.sh:

bash
#!/bin/bash

source ~/scripts/redis-utils.sh

# =============================================================================
# ⚑ Generic Cached API Caller
# =============================================================================

cached_api_call() {
    local cache_key="$1"
    local api_url="$2"
    local cache_seconds="${3:-300}"  # Default 5 minutes
    local api_headers="${4:-}"
    
    echo "πŸ” Checking cache for: $cache_key"
    
    # Try cache first
    local cached_data
    cached_data=$(redis_get_json "$cache_key")
    
    if [ "$cached_data" != "null" ]; then
        local cache_age
        cache_age=$(redis_ttl "$cache_key")
        echo "βœ… Cache HIT! (expires in ${cache_age}s)"
        echo "$cached_data"
        return 0
    fi
    
    echo "πŸ”„ Cache miss β€” calling API..."
    
    # Make API call
    local response
    if [ -n "$api_headers" ]; then
        response=$(curl -s -H "$api_headers" "$api_url")
    else
        response=$(curl -s "$api_url")
    fi
    
    # Validate response (simple JSON check)
    if ! echo "$response" | jq -e . >/dev/null 2>&1; then
        echo "❌ Invalid API response" >&2
        return 1
    fi
    
    # Cache the response
    redis_cache_json "$cache_key" "$response" "$cache_seconds"
    echo "βœ… Cached for ${cache_seconds} seconds"
    
    echo "$response"
}

# Example usage
echo "Fetching data with caching..."
result=$(cached_api_call "users:list" "https://jsonplaceholder.typicode.com/users" 600)
echo "$result" | jq '.[0].name'

πŸ”§ TTL (Time To Live) Guidelines

text
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              RECOMMENDED CACHE DURATIONS                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚  Data Type          TTL          Reason                     β”‚
β”‚  ─────────────────────────────────────────────────────────  β”‚
β”‚  πŸ’° Stock/Prices    5 min        Changes frequently          β”‚
β”‚  🌀️  Weather        30 min       Updates ~hourly             β”‚
β”‚  πŸ₯ Health Status   1 min        Need fresh status          β”‚
β”‚  πŸ‘€ User Sessions   1 hour       Security + usability       β”‚
β”‚  πŸ“Š API Rate Limits 1 hour       Static configuration       β”‚
β”‚  πŸ—ΊοΈ  Locations      24 hours      Rarely change             β”‚
β”‚                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“Š Performance Testing

Compare cached vs non-cached:

bash
#!/bin/bash

source ~/scripts/redis-utils.sh

API_URL="https://api.example.com/data"
CACHE_KEY="perf:test"

echo "πŸš€ Performance Test: Cached vs Non-Cached"
echo "=========================================="

# Test 1: Non-cached
echo -e "\n❌ Without Cache:"
for i in 1 2 3; do
    redis_delete "$CACHE_KEY"  # Clear cache
    
    start=$(date +%s%N)
    curl -s "$API_URL" > /dev/null
    end=$(date +%s%N)
    
    duration=$(( (end - start) / 1000000 ))
    echo "  Request $i: ${duration}ms"
done

# Test 2: Cached
echo -e "\nβœ… With Cache:"
# Pre-populate cache
cached_api_call "$CACHE_KEY" "$API_URL" 300 >/dev/null

for i in 1 2 3; do
    start=$(date +%s%N)
    redis_get "$CACHE_KEY" > /dev/null
    end=$(date +%s%N)
    
    duration=$(( (end - start) / 1000000 ))
    echo "  Request $i: ${duration}ms"
done

πŸŽ“ Best Practices

1. Cache Key Naming

bash
# Good: Hierarchical, descriptive
cache_key="weather:singapore:daily"
cache_key="user:123:profile"
cache_key="api:github:rate_limit"

# Bad: Vague, collision-prone
cache_key="data"
cache_key="temp"

2. Error Handling

bash
fetch_with_cache() {
    local key="$1"
    local url="$2"
    
    # Try cache first
    local cached
    cached=$(redis_get_json "$key")
    
    if [ "$cached" != "null" ]; then
        echo "$cached"
        return 0
    fi
    
    # Fetch with error handling
    local response
    response=$(curl -s --max-time 10 "$url")
    
    if [ $? -ne 0 ] || [ -z "$response" ]; then
        # Return stale cache if available (optional)
        echo "⚠️  API failed, no cache" >&2
        return 1
    fi
    
    # Cache successful response
    redis_cache_json "$key" "$response" 300
    echo "$response"
}

3. Cache Warming

bash
# Pre-populate cache before peak hours
warm_cache() {
    echo "πŸ”₯ Warming cache..."
    
    # Pre-fetch common data
    cached_api_call "config:main" "$API_BASE/config" 3600 >/dev/null
    cached_api_call "users:top" "$API_BASE/users/top" 300 >/dev/null
    cached_api_call "prices:all" "$API_BASE/prices" 300 >/dev/null
    
    echo "βœ… Cache warmed"
}

# Run on cron at 8 AM
0 8 * * * ~/scripts/warm-cache.sh

βœ… Verification Checklist

  • Redis installed and running (redis-cli ping returns PONG)
  • Helper functions saved and executable
  • API calls include error handling
  • Appropriate TTL selected for each data type
  • Cache keys follow naming convention
  • Performance tested (cached vs non-cached)
  • Memory usage monitored (redis_stats)

πŸ› Troubleshooting

Redis not running

bash
# Check status
sudo systemctl status redis

# Start Redis
sudo systemctl start redis

# Auto-start on boot
sudo systemctl enable redis

Connection refused

bash
# Check Redis is listening
netstat -tlnp | grep 6379

# Check firewall
sudo ufw allow 6379  # If needed locally

Memory issues

bash
# Check memory usage
redis-cli info memory

# Set max memory in redis.conf
maxmemory 256mb
maxmemory-policy allkeys-lru  # Evict least recently used


Questions? Join the OpenClaw Discord ⚑

Ada Pertanyaan? Yuk Ngobrol!

Butuh bantuan setup OpenClaw, konsultasi IT, atau mau diskusi project engineering? Book a call langsung β€” gratis.

Book a Call β€” Gratis

via Cal.com β€’ WITA (UTC+8)

Newsletter

Subscribe to Newsletter

Artikel baru, automation notes, dan engineering insight. Clean inbox, no spam.

Dengan subscribe, kamu setuju menerima update seperlunya.

F
Zainul Fanani

Founder, Radian Group. Engineering & tech enthusiast.

Lihat profil lengkap β†’