> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gcore.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Cache

> FastEdge Cache is a fast key-value store for transient request-time state, atomic counters, and rate limiting at each POP.

Cache is a fast key-value store co-located with each FastEdge POP (Point of Presence). It is intended for transient, request-time state — counters, memoized computations, idempotency tokens — and is available to every FastEdge application on a paid plan at runtime without needing to be created or linked in advance.

> [!NOTE]
>
> Cache does not need to be created or linked to your application. It is available at runtime by importing the cache module from the SDK.

## Behavior and limits

Cache data lives inside a single POP. Writes are not replicated to other POPs, and a value written in one location is not visible from another. Within a POP, reads and writes are strongly consistent.

Entries are evictable and carry no durability guarantee. A value may disappear before its expiration if the POP is under memory pressure. Cache is not a substitute for persistent storage.

Integer values can be incremented and decremented atomically within a POP, making Cache a natural fit for rate limiting and fixed-window throttling. The `incr` function accepts a signed delta — a positive value increments, a negative value decrements.

The JavaScript SDK provides a `getOrSet` operation: if the key exists, its value is returned immediately; if not, a provided callback computes the value, stores it, and returns it. This is useful for read-through caching where computation is expensive.

`purge` removes all cache keys visible to the application; `purgePrefix` removes all keys whose names begin with a given string. Both return the number of keys deleted. Because Cache is shared across all applications for an account at a POP, these operations affect every key visible to your account at that POP, not only those written by the calling application.

## Cache vs Edge Storage

Cache and [Edge Storage](/fastedge/kv-stores/how-it-works) solve different problems. Use this table to decide which one fits your workload.

| | Cache | Edge Storage |
| - | - | - |
| Scope | Single POP | Globally replicated to all POPs |
| Consistency | Strong (within a POP) | Eventual (1–2 seconds globally) |
| Durability | Transient, evictable | Durable, backed by a central database |
| Provisioning | None — available at runtime on paid plans | Created in the Customer Portal and linked to your application |
| Writes from the API | No (runtime only) | Yes |
| Atomic counters | Yes (`incr`; `decr` JS only) | No |
| Typical workloads | Rate limits, response memoization, idempotency keys, per-request deduplication | Configuration, feature flags, lookup tables, blocklists, sorted sets, Bloom Filters |

A common pattern is to use both together: store the source of truth in Edge Storage and use Cache to memoize derived results or enforce per-POP rate limits.

## Available operations

| Operation | Description |
| - | - |
| `get` | Fetch a cached value by key. Returns `None`/`null` on a miss. |
| `set` | Write or overwrite a value with an optional TTL. |
| `delete` | Remove a key from the cache. |
| `exists` | Check whether a key is present without fetching its value. |
| `incr` | Atomically increment (or decrement) an integer counter. |
| `decr` | Decrement a counter. JavaScript SDK only. |
| `expire` | Set or update the TTL of an existing key. Returns `false` if the key no longer exists. |
| `getOrSet` | Fetch a value, or compute and store it if missing. JavaScript SDK only. |
| `purge` | Delete all cache keys visible to the application at the current POP. |
| `purgePrefix` | Delete all keys whose names begin with a given prefix. |

In the JavaScript SDK, expiration is specified per write as `{ ttl: seconds }`, `{ ttlMs: milliseconds }`, or `{ expiresAt: unixTimestamp }`. In the Rust SDK, TTL is always in milliseconds (`Option<u64>`). Entries with no expiration remain until evicted.

## SDK examples

The following examples cover the most common Cache patterns. For the full API reference, see the [JavaScript SDK](https://g-core.github.io/FastEdge-sdk-js/reference/fastedge/cache/) and [Rust SDK](https://docs.rs/fastedge/latest/fastedge/cache/) documentation.

### Read and write a value

**JavaScript**

```javascript theme={null}
import { Cache } from 'fastedge::cache';

await Cache.set('config:feature-x', 'enabled', { ttl: 300 }); // 5-minute TTL

const value = await Cache.get('config:feature-x');
if (value === null) {
  // cache miss — compute and store
}

await Cache.delete('config:feature-x');
```

**Rust**

```rust theme={null}
use fastedge::cache;

cache::set("config:feature-x", b"enabled".to_vec(), Some(300_000))?; // 5 min in ms

match cache::get("config:feature-x")? {
    Some(data) => {
        let value = String::from_utf8_lossy(&data);
        // use value
    }
    None => {
        // cache miss — compute and store
    }
}

cache::delete("config:feature-x")?;
```

### Rate limiting with an atomic counter

**JavaScript**

```javascript theme={null}
import { Cache } from 'fastedge::cache';

const ip = event.client.address ?? 'unknown';
const key = `rl:${ip}`;

const count = await Cache.incr(key);
if (count === 1) {
  // First request in the window — set a 60-second TTL
  await Cache.expire(key, { ttl: 60 });
}

if (count > 100) {
  return new Response('Too Many Requests', { status: 429 });
}
```

**Rust**

```rust theme={null}
use fastedge::cache;

let ip = request.headers()
    .get("x-real-ip")
    .and_then(|v| v.to_str().ok())
    .unwrap_or("unknown");

let key = format!("rl:{ip}");

// Increment by 1; create the counter at 0 if it does not exist
let count = cache::incr(&key, 1)?;

if count == 1 {
    // First request in the window — set a 60-second TTL (60 000 ms)
    cache::expire(&key, 60_000)?;
}

if count > 100 {
    return Ok(Response::builder()
        .status(429)
        .body(Body::from("Too Many Requests"))?);
}
```
