Every Sinch Function has access to a shared key-value cache. In development it uses in-memory storage. In production, the cache is persistent across restarts and shared across all instances of your function.
| Operation | Node.js | C# |
|---|---|---|
| Write | cache.set(key, value, ttl?) | cache.Set(key, value, ttl?) |
| Read | cache.get<T>(key) | cache.Get<T>(key) |
| Check existence | cache.has(key) | cache.Exists(key) |
| Delete | cache.delete(key) | cache.Delete(key) |
| Extend TTL | cache.extend(key, seconds) | — |
| List keys | cache.keys(pattern?) | cache.GetKeys() |
| Batch read | cache.getMany(keys) | — |
Default TTL: 3600 seconds (1 hour).
import type { FunctionContext, FunctionRequest } from '@sinch/functions-runtime';
export async function myHandler(context: FunctionContext, request: FunctionRequest) {
const cache = context.cache;
await cache.set('greeting', 'Hello!');
const value = await cache.get<string>('greeting'); // 'Hello!'
}await cache.set('short-lived', 'value', 60); // 60 seconds
await cache.set('persistent', 'value', 86400 * 30); // 30 days
await cache.extend('session:abc123', 300); // extend by 5 minutesValues are JSON-serialized automatically.
interface UserProfile {
name: string;
plan: string;
createdAt: string;
}
await cache.set<UserProfile>(
'user:123',
{
name: 'Alice',
plan: 'pro',
createdAt: new Date().toISOString(),
},
3600
);
const profile = await cache.get<UserProfile>('user:123');Store caller state across voice callbacks using the call ID as key.
// In ICE handler
await context.cache.set(
`session:${event.callId}`,
{
callerNumber: event.cli,
startTime: Date.now(),
},
600
);
// In PIE handler
const session = await context.cache.get<{ callerNumber: string; startTime: number }>(
`session:${event.callId}`
);async function isRateLimited(
cache: IFunctionCache,
caller: string,
maxPerHour = 10
): Promise<boolean> {
const key = `rate:${caller}`;
const current = await cache.get<number>(key);
if (current === null) {
await cache.set(key, 1, 3600);
return false;
}
if (current >= maxPerHour) return true;
await cache.set(key, current + 1, 3600);
return false;
}async function getCustomer(cache: IFunctionCache, phone: string) {
const cacheKey = `customer:${phone}`;
const cached = await cache.get<Customer>(cacheKey);
if (cached) return cached;
const customer = await fetchCustomerFromApi(phone);
if (customer) await cache.set(cacheKey, customer, 300);
return customer;
}| Aspect | Development | Production |
|---|---|---|
| Backend | In-memory | Persistent store |
| Persistence | Lost on restart | Survives restarts |
| Sharing | Single process only | Shared across all instances |
| TTL enforcement | Approximate | Exact |
The IFunctionCache interface is identical in both environments. No code changes needed when deploying.