# Cache Lifetimes

Server cache entries share a common model for freshness, tags, invalidation, and storage. These
policies are shared by [Page Caching](./page-caching.md), [RSC Caching](./rsc-caching.md), and
[Caching in Server Components](./server-components.md).

## Lifetimes

A server cache entry is fresh until `revalidate`, stale until `expire`, and unusable after `expire`:

| Setting      | Behavior                                                                                                 |
| ------------ | -------------------------------------------------------------------------------------------------------- |
| `revalidate` | The entry is fresh until this time passes. Afterward, it is stale but can still be served and refreshed. |
| `expire`     | The entry is usable until this time passes. Afterward, it must be rendered again.                        |

Without `expire`, an entry stays usable for a year, so `revalidate` alone keeps serving the entry
while it refreshes in the background. Set `expire` only when a stale entry must stop being served.

When several lifetime settings contribute to one render, the shortest value wins. `expire` must be
at least as long as `revalidate`, a shorter value is clamped to `revalidate`. Lifetimes are capped
at one year.

::cache-lifetime-aggregation
::

Each cache scope owns its own entry, but settings from a nested scope also contribute to the parent
page and RSC entries. In this example, `getProducts` and `getInventory` keep separate entries,
while their shortest `revalidate` and `expire` values constrain the parent entries and their `tags`
are merged into them. Parent settings do not flow down into nested entries.

## Tags

A tag is a label shared by entries that should be invalidated together. When a tag is invalidated,
every matching entry is treated as expired on its next read and refreshed as needed.

Tags from nested scopes are merged into parent entries, so invalidating a tag of a nested scope will
also invalidate the parent scopes.

Server tags belong to server entries, client segment tags are separate and are managed by the
client router. See [Segment Caching](./segment-caching.md).

## `cacheLife`

Use `cacheLife` to set the `revalidate` and optional `expire` values for the current server cache
scope:

```tsx
import { cacheLife } from "@rebask/core/cache"

export default async function ProductsPage() {
  cacheLife({ revalidate: 300, expire: 3600 })
  return <ProductList />
}
```

The scope of a `cacheLife` call determines which entries receive its settings. In a page or layout,
the settings contribute to the page's HTML and RSC entries. Inside a
[`"use cache"`](./server-components.md#use-cache) function, they apply to that function's entry and
flow upward to the containing render's page and RSC entries.

Multiple `cacheLife` calls are aggregated using the most restrictive lifetime. The smallest
`revalidate` and `expire` values are used. `expire` is kept at least as long as `revalidate`.

## `cacheTag`

Use `cacheTag` to associate the current server cache scope with one or more tags:

```tsx
import { cacheTag } from "@rebask/core/cache"

export async function getProducts() {
  cacheTag("products")
  return db.products.findAll()
}

export async function getProduct(id: string) {
  cacheTag("products", `product:${id}`)
  return db.products.find(id)
}
```

Use `cacheTag` in a page, layout, or any other Server Component to tag the page and RSC entries
produced by that render. It can also be called inside a `"use cache"` function to tag that
function's entry and contribute the tag to the containing page and RSC entries. Tags are accumulated
on each scope's own entry and also merged into their parent entries.

## `revalidateTag`

Use `revalidateTag` from server-side code to invalidate every server entry associated with a tag:

```ts
"use server"

import { revalidateTag } from "@rebask/core/cache"

export async function updateProducts() {
  await db.products.updateAll()
  await revalidateTag("products")
}
```

It can be called from [Server Functions](../server-functions.md),
[route handlers](../routing/route-handlers.md), and Server Components. The client router's
[`router.revalidateTag`](../routing/navigations.md#userouter-routerrevalidatetag) is a separate API
that only revalidates client segments.

When a tag is revalidated, Rebask records the invalidation time. Entries carrying that tag from
before the invalidation are treated as expired on their next read and produce a new value.
