Skip to content

[feat] Pluggable session cache driver (Redis or in-memory) #117

Description

@nathan-mittelette

Problem

TRAWL currently hard-couples the Tier 2 session cache to Redis. When Redis is unavailable — connection timeout, network issue, or simply not deployed — Tier 2 is silently disabled and every request falls back to a fresh CF solve (Tier 3) or residential proxy (Tier 4). This wastes browser pool capacity and adds latency/cost on every call.

For single-instance and low-resource deployments (home labs, NAS, small VPS), Redis is operational overhead with no benefit: there is no second instance to share sessions with. Today there is no way to run TRAWL without Redis while keeping Tier 2 active.

Proposed solution

Introduce a pluggable session cache driver so the cache backend can be selected at startup via a new env var:

SESSION_CACHE_DRIVER=redis   # default, current behaviour — shared across instances
SESSION_CACHE_DRIVER=memory  # in-process Map, zero external dependencies

This gives single-instance deployments a local session cache without requiring Redis, while keeping Redis as the default to preserve cross-instance session sharing and avoid breaking existing setups.

Implementation shape

  • New ISessionCache interface in packages/browser/src/session.ts extracting the existing SessionCache contract (connect, save, load, invalidate).
  • New MemorySessionCache class in packages/browser/src/memory-session.ts implementing ISessionCache with a Map<string, Entry> and TTL-based expiry.
  • apps/api/src/deps.ts selects the driver at startup based on SESSION_CACHE_DRIVER.
  • New SESSION_CACHE_DRIVER config key in apps/api/src/config.ts.
  • Redis stays the default to avoid breaking existing deployments and to preserve cross-instance session sharing.

The ISessionCache interface is designed so additional drivers (e.g. SQLite, Valkey, KeyDB) can be added later without touching the orchestrator or tier logic.

Alternatives considered

  • Auto-fallback to memory when Redis fails: rejected because it hides a misconfiguration. An explicit SESSION_CACHE_DRIVER=memory is clearer — the operator knows they chose single-instance mode and sessions won't be shared across instances.
  • Keep Redis-only and document the requirement: doesn't solve the core problem. Small-instance users who don't need cross-instance sharing still pay the operational cost of running Redis.

Tier impact

  • Fit inside an existing tier — this strengthens Tier 2 (cached session) by making it available without Redis.
  • Require a new tier or solver
  • Apply cross-cutting (caching, observability, config)

Willingness to contribute

  • I'd like to implement this myself and open a PR
  • I'd be happy with a maintainer implementing it
  • Just a discussion for now

Additional context

The MemorySessionCache is per-instance only — sessions solved on instance A are not visible to instance B. This is the expected trade-off for single-instance deployments and would be documented in the class JSDoc and in the startup log line.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions