Skip to content
Data
Skill

/walkeros-using-store-cache

`Flow.Store.cache` wraps any store with a read-through, write-through cache tier. Reads check the cache first, fall through to the backing on miss, and populate every tier on the unwind. Writes go to the backing first, then to the cache best-effort.

BOOST
From plugin
walkeros
34822 skills
Install
$ npx -y skills add elbwalker/walkerOS --skill walkeros-using-store-cache --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/walkeros-using-store-cache

Context preview

The summary Claude sees to decide when to auto-load this skill.

`Flow.Store.cache` wraps any store with a read-through, write-through cache tier. Reads check the cache first, fall through to the backing on miss, and populate every tier on the unwind. Writes go to the backing first, then to the cache best-effort.

SKILL.md

walkeros-using-store-cache.SKILL.md
name: walkeros-using-store-cache
description:
  Use when adding read-through caching to a walkerOS store, memoizing a slow
  API/Sheets backing, composing multi-tier cache chains, or deduplicating
  concurrent store reads. Covers recipes, TTL choice, error policy, and
  observability counters.

Using store-level cache

Overview

`Flow.Store.cache` wraps any store with a read-through, write-through cache tier. Reads check the cache first, fall through to the backing on miss, and populate every tier on the unwind. Writes go to the backing first, then to the cache best-effort.

The wrapping is transparent: a transformer wired to `$store.crm` does not know whether reads hit a memory cache, a GCS tier, or the underlying Sheets API.

**Core principle:** the cache is advisory. Backing is the source of truth. Failed cache operations degrade performance, never correctness.

**TTL is owned by the cache layer, not the store.** The store persists structured values; the cache wrapper manages expiry via the per-rule `ttl`. An expired entry is treated as a miss and re-fetched from the backing. Caching works over any structured backing.

A store's byte-native `file` mode (`config.file: true`) is for serving raw assets byte-exact, not for caching. The cache wraps structured stores, so `flow_validate` warns when a store sets both `file: true` and `cache`. Drop one: serve bytes with `file: true` and no cache, or cache a structured store with no `file`.

When to use this skill

  • A transformer reads the same key many times across events (sessions, user

lookups, product catalog enrichment)

  • A store has rate limits or slow HTTP round-trips (Sheets, custom API, S3

metadata)

  • You need to deduplicate concurrent reads on a cold key (thundering herd)
  • You want to compose multi-tier caches (memory → GCS → Sheets)
  • You're migrating off `@walkeros/store-memory` (removed in favor of the

built-in tier)

Minimal recipe: cache a Sheets store

The talk-demo use case. A `sessions` lookup runs on every event but most events in a session share the same key.

{
  "stores": {
    "sessions": {
      "package": "@walkeros/server-store-sheets",
      "config": {
        "credentials": "$var.sheetsCredentials",
        "settings": {
          "id": "1AbC...",
          "sheet": "Sessions"
        }
      },
      "cache": { "rules": [{ "ttl": 300 }] }
    }
  },
  "transformers": {
    "sessionLookup": {
      "code": {
        "type": "session-lookup",
        "push": "$code:async (event, context) => { if (!event.user?.session) return; const session = await context.env.store.get(event.user.session); if (session) return { event: { ...event, data: { ...event.data, session } } }; }"
      },
      "env": { "store": "$store.sessions" }
    }
  }
}

walkerOS ships no generic lookup transformer, so the consumer here is an inline `code` transformer. Any transformer or destination that reads its `env.store` works the same way.

The first lookup hits Sheets and populates the built-in in-memory tier with a 300-second TTL. The next 300 seconds of identical reads hit memory and skip the Sheets API.

Without the cache: 60 events in 60 seconds = 60 Sheets reads = quota tripped (60 req/min limit) in one minute. With the cache: 60 events in 60 seconds = 1 Sheets read.

Recipe: memoize an object storage store

Same shape, longer TTL because every read is a network round-trip to the bucket:

{
  "stores": {
    "users": {
      "package": "@walkeros/server-store-gcs",
      "config": {
        "settings": { "bucket": "my-user-records", "prefix": "users/" }
      },
      "cache": { "rules": [{ "ttl": 3600 }] }
    }
  }
}

One-hour TTL is reasonable when user records change rarely. Use `flow_validate` to verify the config; use `flow_simulate` with a representative event to confirm the cache hit rate.

Recipe: TTL by key prefix

Different keys can have different TTLs. Rules evaluate top-down, first match wins. The match context is `{ key, value? }`, not event data:

"cache": {
  "rules": [
    { "match": { "key": "key", "operator": "prefix", "value": "session:" }, "ttl": 300 },
    { "match": { "key": "key", "operator": "prefix", "value": "user:" }, "ttl": 3600 },
    { "ttl": 60 }
  ]
}
  • `session:*` keys cache for 5 minutes
  • `user:*` keys cache for 1 hour
  • Everything else caches for 1 minute

A rule without `match` always matches. Place it last as a fallback.

Recipe: multi-tier composition (memory → GCS → Sheets)

When the working set exceeds the memory tier's capacity, or cached values should survive restarts and be shared across instances, add an object storage layer between memory and the cold backing. The consumer still wires to `$store.crm`; the tiers resolve automatically. The cache tier must be fs, S3, GCS, or the built-in memory tier: the Sheets store cannot hold cache entries.

{
  "stores": {
    "files": {
      "package": "@walkeros/server-store-gcs",
      "config": {
        "settings": { "bucket": "my-cache-bucket", "prefix": "cache/" }
      },
      "cache": { "rules": [{ "ttl": 300 }] }
    },
    "crm": {
      "package": "@walkeros/server-store-sheets",
      "config": { "settings": { "id": "1AbC...", "sheet": "Customers" } },
      "cache": {
        "store": "files",
        "rules": [{ "ttl": 86400 }]
      }
    }
  },
  "transformers": {
    "crmLookup": {
      "code": {
        "type": "crm-lookup",
        "push": "$code:async (event, context) => { if (!event.user?.id) return; const crm = await context.env.store.get(event.user.id); if (crm) return { event: { ...event, data: { ...event.data, crm } } }; }"
      },
      "env": { "store": "$store.crm" }
    }
  }
}

Lookup chain on `crm.get(K)`:

1. `crm`'s tier is the `files` store. The `files` wrapper checks its own tier (memory `__cache`) first, then GCS. HIT, return. A GCS HIT also populates memory. 2. On all MISS, call the underlying Sheets store. Each traversed tier pop

Read more
Ships withwalkeros

From browser to BigQuery and ad platforms - warehouse-native, and ready for AI agents via MCP.

Get the whole plugin

Other skills on walkeros.