# ZoneCache

The ZoneCache stores data in a shared cache. This cache is in the same zone (the
same data center or cluster) as your API - it's not globally distributed, but
rather designed to be low-latency. Common uses include caching configuration,
session, or other data that needs to be frequently accessed with low latency.

The ZoneCache can store any JSON serializable data. Each cached item has a
time-to-live (TTL) after which it expires and is removed from the cache. Each
cached object can be up to 512 MB in size.

There's an demonstration of ZoneCache use in the
[Per User Rate Limits Using a Database](../articles/per-user-rate-limits-using-db.mdx)
example.

## Constructor

```ts
new ZoneCache<T = unknown>(name: string, context: ZuploContext)
```

Creates a new cache instance for the specified zone.

- `name` - A unique identifier for the cache
- `context` - The [ZuploContext](./zuplo-context.mdx) object
- `T` - The type of data stored in the cache (defaults to `unknown`)

## Methods

**`get`**

Retrieves a value from the cache. Returns `undefined` if the key doesn't exist
or has expired.

```ts
get(key: string): Promise<T | undefined>
```

**`put`**

Stores a value in the cache with a time-to-live (TTL) in seconds. The data will
be JSON serialized.

```ts
put(key: string, data: T, ttlSeconds: number): Promise<void>
```

:::note

Objects that don't serialize cleanly to JSON (like the `Headers` object) won't
be readable after storage.

:::

**`delete`**

Removes a value from the cache.

```ts
delete(key: string): Promise<void>
```

## Example

```ts
import { ZoneCache, ZuploContext, ZuploRequest } from "@zuplo/runtime";

interface UserData {
  id: string;
  name: string;
  email: string;
}

export default async function handler(
  request: ZuploRequest,
  context: ZuploContext,
) {
  const cache = new ZoneCache<UserData>("user-cache", context);

  // Try to get user from cache
  const userId = request.params.userId;
  let userData = await cache.get(userId);

  if (!userData) {
    // Not in cache, fetch from API
    const response = await fetch(`https://api.example.com/users/${userId}`);
    userData = await response.json();

    // Cache for 5 minutes
    await cache.put(userId, userData, 300);
  }

  return new Response(JSON.stringify(userData));
}
```

## Performance tips

When writing to the cache, you may not want to `await` the operation to
complete. This can improve response times:

```ts
// Fire and forget pattern - don't wait for cache write
cache.put("key", data, 60).catch((err) => context.log.error(err));
```

Always catch errors when using the fire-and-forget pattern to avoid unhandled
promise rejections.

## When to use ZoneCache

Use ZoneCache when you need low-latency access to frequently used data that's
stored in a single zone. It's ideal for caching configuration data, session
information, or results from external API calls that are expensive or slow to
retrieve.

Avoid using ZoneCache for large datasets or data that needs to be globally
distributed, as it's designed for small, simple objects within a single zone. It
is also not suitable to be used as an OLTP to read/write important data, it's
just a cache - very useful but not a database or key/value store.

## Limits

For full Zuplo platform limits see the
[Zuplo Limits documentation](../articles/limits.mdx).

- Maximum size per cached item: 512 MB
- Maximum cache calls per request: 1000
