
Description
Cache data in Redis from Encore.ts using `CacheCluster` and typed keyspaces from `encore.dev/storage/cache`. Type-safe key/value access with TTLs, atomic increments, and per-keyspace data shapes.
SKILL.md
Encore Caching (Redis)
Instructions
Encore's cache is a typed wrapper around Redis. Declare a CacheCluster once, then create Keyspace objects for each shape of data you need.
Cluster
import { CacheCluster } from "encore.dev/storage/cache";
const cluster = new CacheCluster("my-cache", {
evictionPolicy: "allkeys-lru",
});
Reference a cluster from another service: const cluster = CacheCluster.named("my-cache");
Eviction policies: "allkeys-lru" (default), "noeviction", "allkeys-lfu", "allkeys-random", "volatile-lru", "volatile-lfu", "volatile-ttl", "volatile-random".
Keyspace types
Each keyspace has a key shape (used to build the Redis key from keyPattern) and a value type.
import {
StringKeyspace,
IntKeyspace,
FloatKeyspace,
StructKeyspace,
StringListKeyspace,
NumberListKeyspace,
StringSetKeyspace,
NumberSetKeyspace,
expireIn,
} from "encore.dev/storage/cache";
// Strings
const tokens = new StringKeyspace<{ tokenId: string }>(cluster, {
keyPattern: "token/:tokenId",
defaultExpiry: expireIn(3600 * 1000),
});
await tokens.set({ tokenId: "abc" }, "value");
const val = await tokens.get({ tokenId: "abc" }); // undefined on miss
// Integers (atomic counters)
const counters = new IntKeyspace<{ userId: string }>(cluster, {
keyPattern: "requests/:userId",
defaultExpiry: expireIn(10 * 1000),
});
const count = await counters.increment({ userId: "user123" }, 1);
// Structs (JSON)
interface UserProfile { name: string; email: string; }
const profiles = new StructKeyspace<{ userId: string }, UserProfile>(cluster, {
keyPattern: "profile/:userId",
defaultExpiry: expireIn(3600 * 1000),
});
await profiles.set({ userId: "123" }, { name: "Alice", email: "alice@example.com" });
// Lists
const recent = new StringListKeyspace<{ userId: string }>(cluster, {
keyPattern: "recent/:userId",
});
await recent.pushRight({ userId: "user123" }, "item1", "item2");
// Sets
const tags = new StringSetKeyspace<{ articleId: string }>(cluster, {
keyPattern: "tags/:articleId",
});
await tags.add({ articleId: "post1" }, "typescript", "encore");
const has = await tags.contains({ articleId: "post1" }, "typescript");
Multi-field key patterns
interface Key { userId: string; resourcePath: string; }
const requests = new IntKeyspace<Key>(cluster, {
keyPattern: "requests/:userId/:resourcePath",
defaultExpiry: expireIn(10 * 1000),
});
Expiry helpers
import {
expireIn, // milliseconds
expireInSeconds,
expireInMinutes,
expireInHours,
expireDailyAt, // a specific UTC time each day
neverExpire,
keepTTL, // keep existing TTL when updating
} from "encore.dev/storage/cache";
Write options
await keyspace.set(key, value, { expiry: expireInMinutes(30) });
await keyspace.set(key, value, { expiry: keepTTL });
await keyspace.setIfNotExists(key, value); // throws CacheKeyExists if present
await keyspace.replace(key, value); // throws CacheMiss if absent
Errors
import { CacheMiss, CacheKeyExists } from "encore.dev/storage/cache";
const value = await keyspace.get(key); // undefined on miss (does not throw)
Guidelines
- Declare
CacheClusterand keyspaces at package level. - Pick the most specific keyspace type —
IntKeyspacefor counters gives you atomicincrement/decrementfor free. get()returnsundefinedon miss;replace()andsetIfNotExists()throw on conflict.- Local development uses an in-memory Redis with a ~100-key cap — don't load-test it.
- For durable storage, use
encore-database(Postgres) orencore-bucket(object storage) instead.
More skills from the skills repository
View all 28 skillsencore-api
build type-safe APIs with Encore
Apr 6API DevelopmentEncoreTypeScriptencore-auth
implement Encore.ts authentication
Apr 6AuthEncoreTypeScriptencore-bucket
store files in Encore.ts buckets
May 16BackendEncoreFile StorageFile Uploads +1encore-code-review
review Encore.ts code
Apr 6Code ReviewEncoreTypeScriptencore-cron
schedule recurring jobs in Encore.ts
May 16AutomationBackendEncoreScheduling +1encore-database
build Encore databases
Apr 6DatabaseEncoreORMTypeScript
More from Encore
View publisherencore-frontend
connect frontend to Encore backend
skills
Apr 6EncoreFrontendNext.jsReactencore-getting-started
build and run applications with Encore.ts
skills
Apr 6API DevelopmentBackendEncoreLocal Development +2encore-go-api
build APIs with Encore Go
skills
Apr 6API DevelopmentEncoreGoencore-go-auth
implement authentication with Encore Go
skills
Apr 6AuthBackendEncoreGoencore-go-bucket
store files in Encore Go buckets
skills
May 16BackendEncoreFile StorageGo +1