Skip to content

[Performance] Add Redis Caching Layer for Frequent Blockchain Data Queries #12

Description

@KarenZita01

Description

Many API endpoints in EquipChain will query blockchain state through the Soroban SDK (Issue #3), which introduces network latency and RPC rate limits. To improve response times and reduce dependency on the Soroban network, a Redis caching layer should be implemented to store frequently accessed blockchain data with appropriate time-to-live (TTL) policies.

The caching layer must support the following operations: automatic caching of Soroban contract read results with configurable TTL (default 60 seconds for meter readings, 300 seconds for configuration data), cache invalidation when new data is written to the blockchain (write-through or write-behind patterns), cache warming for high-priority queries, and cache health monitoring with hit/miss metrics. The implementation should use the ioredis library for Redis connectivity with support for Redis Cluster and Sentinel for high availability in production.

A cache abstraction layer should be created to abstract Redis specifics from the business logic. This abstraction should expose a simple get(key), set(key, value, ttl), del(key), and flush(pattern) API. The cache keys should follow a consistent naming convention: equipchain:{entity}:{id}:{field} (e.g., equipchain:meter:device123:lastReading). The layer should gracefully handle Redis connection failures by falling back to direct Soroban queries without crashing the application.

Technical Context & Impact

  • Dependencies: ioredis (^5.x). Redis server (Docker container from Issue [DevOps] Containerize Application with Docker Multi-Stage Build and Docker Compose #10). Environment variables: REDIS_URL (default redis://localhost:6379), REDIS_PASSWORD (optional), CACHE_DEFAULT_TTL (default 60).
  • Architecture: New src/services/cache.js providing the cache abstraction. New src/middleware/cache.js providing an Express middleware for automatic caching of GET responses. Integration with Soroban service to cache read results.
  • Impact: Significant performance improvement for read-heavy endpoints. Reduced load on Soroban RPC endpoints. Better user experience with faster response times. This is essential before launching any public-facing dashboard or API.

Step-by-Step Implementation Guide

  1. Install ioredis: Run npm install ioredis. Add REDIS_URL to .env file. Add the redis service to docker-compose.yml (align with Issue [DevOps] Containerize Application with Docker Multi-Stage Build and Docker Compose #10).
  2. Create Cache Service: Write src/services/cache.js exporting a class CacheService. Constructor accepts Redis URL, connects with retry strategy (exponential backoff, max 10 retries). Methods: get(key), set(key, value, ttl), del(key), flush(pattern), health(). Use JSON serialization for complex objects. Handle connection errors gracefully with fallback logging.
  3. Create Caching Middleware: Write src/middleware/cache.js exporting cache(ttl) that returns middleware. Before handler execution, check if request URL + query params match a cached key. If hit, return cached response directly. If miss, intercept the response to cache it before sending. Only cache GET requests. Vary cache key by authentication status.
  4. Integrate with Soroban Service: Update the Soroban service (Issue [Feature] Integrate Soroban SDK for Direct Blockchain Data Access and Contract Interaction #3) to use the cache service. In readContract(), check cache before making RPC call. On successful read, store result in cache. On write operations, invalidate relevant cache keys.
  5. Write Tests: Create tests/unit/cache.test.js with a Redis mock (or use a real Redis instance via Docker). Test get/set/del operations, TTL expiration, fallback behavior when Redis is down. Create tests/integration/cache.test.js testing the caching middleware with the Express app.

Verification & Testing Steps

  1. Start the application with Redis running (via Docker Compose from Issue [DevOps] Containerize Application with Docker Multi-Stage Build and Docker Compose #10). Verify the server logs indicate successful Redis connection.
  2. Call a cached GET endpoint twice. Measure response times: the second call should be significantly faster (cache hit).
  3. Manually connect to Redis via redis-cli and verify cache keys exist with the naming convention equipchain:*. Check TTL is set correctly.
  4. Stop the Redis container and make a cached request — verify the API falls back to the Soroban RPC call and returns data without crashing.
  5. Perform a write operation that invalidates a cache key — verify the next read fetches fresh data from Soroban rather than stale cache.

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions