Cache
Cache is a built-in config property available on every step type (source, transformer, destination). It prevents redundant processing by caching results and serving them on subsequent matching requests.
Configuration
Add cache to any step in your flow config:
"sources": {
"express": {
"package": "@walkeros/server-source-express",
"cache": {
"rules": [
{
"match": { "key": "ingest.method", "operator": "eq", "value": "GET" },
"key": ["ingest.method", "ingest.path"],
"ttl": 300
}
]
}
}
}
Cache Rule Properties
| Property | Type | Description |
|---|---|---|
match | MatchExpression | When to apply this cache rule |
key | string[] | Dot-paths to build the cache key from |
ttl | number | Time-to-live in seconds |
update | Record<string, Value> | Optional modifications applied on read |
match is optional, omit it for an always-match rule.
Cache Properties
| Property | Type | Default | Description |
|---|---|---|---|
stop | boolean | false (true for sources) | Stop flow on cache HIT and skip remaining steps, returning the cached value |
store | string | Built-in memory | Reference to a store in flow.stores |
namespace | string | (none) | Optional key prefix. Omit to write keys directly to the store. Same store + same key + same namespace = same cache entry. |
rules | CacheRule[] | Required | At least one cache rule |
Behavior by Step Type
Source Cache (stop by default)
Source cache intercepts requests before the pipeline runs. Sources default to stop: true. On cache HIT, the cached respond value is returned immediately and the pipeline is skipped. Set stop: false to skip only the source step and let the pipeline continue.
"sources": {
"express": {
"cache": {
"rules": [
{ "match": { "key": "ingest.method", "operator": "eq", "value": "GET" }, "key": ["ingest.method", "ingest.path"], "ttl": 300 }
]
}
}
}
Transformer Cache (step-level)
Transformer cache skips the transformer's execution on HIT but continues the chain with the cached event. Useful for expensive computations like API enrichment. With stop: true, the remaining chain stops on HIT and downstream transformers and destinations are skipped.
Pre-collector transformer caches with stop: true halt the entire pipeline on HIT, destinations do not see the event. Destination caches with stop: true halt only the per-destination delivery, sibling destinations still receive the event.
"transformers": {
"enricher": {
"package": "@walkeros/server-transformer-enricher",
"cache": {
"rules": [
{ "key": ["event.name"], "ttl": 60 }
]
}
}
}
Destination Cache (deduplication)
Destination cache skips the push on HIT, preventing duplicate events from reaching the destination. Other destinations still receive the event. With stop: true, the before transformer chain is also skipped on HIT.
"destinations": {
"ga4": {
"package": "@walkeros/web-destination-ga4",
"cache": {
"rules": [
{ "key": ["event.name", "event.data.id"], "ttl": 300 }
]
}
}
}
Key Resolution
Cache keys use dot-path resolution from a structured context:
ingest.method: request method from source ingestingest.path: request path from source ingestevent.name: event nameevent.data.id: nested event data fieldevent.user.loggedIn: user properties
Update Rules
Use update to modify the result on both HIT and MISS:
"cache": {
"rules": [{
"key": ["ingest.method", "ingest.path"],
"ttl": 300,
"update": {
"headers.X-Cache": { "key": "cache.status" },
"headers.Cache-Control": { "value": "public, max-age=300" }
}
}]
}
cache.status resolves to "HIT" or "MISS". Static values use { "value": "..." }.
Custom Store
By default, cache uses a shared in-memory store. Reference a custom store for persistence:
{
"stores": {
"redis": { "package": "@walkeros/server-store-redis" }
},
"sources": {
"express": {
"cache": {
"store": "redis",
"rules": [...]
}
}
}
}
Custom stores can be either synchronous (in-memory) or asynchronous (file system, Redis, HTTP, the cache wrapper). Cache lookups await the underlying store.get internally, so HIT/MISS semantics behave identically regardless of which backing you wire.
Migration from prior v4 cache
If you're upgrading from an earlier v4 build, three breaking changes apply:
cache.fullis nowcache.stop. Search-and-replace"full"for"stop"in everycacheblock. Default behavior unchanged (sources default tostop: true, transformers and destinations default tostop: false).cache.match: "*"is now omitted. Drop the"match": "*"entry from rules. A rule with nomatchmatches every event, the behavior is identical to the previous wildcard.- Implicit per-step namespacing is gone. Previous builds prefixed cache keys with
s:,t:, ord:based on step type, so a source and a destination writing the same key never collided. That prefix is no longer applied. If you share a store across step types and need isolation, setcache.namespaceexplicitly (for example"namespace": "source").