# Caching - SSR websites

> How SSR websites stay fast - templates compiled when a file is saved, engines kept per website, pages kept by the server for everyone or per visitor, stale-while-revalidate, tags dropped with ctx.revalidate, and public files kept by browsers.

Source: https://docs.apimaker.dev/v4/docs/ssr/caching.html

A website is fast before any cache : its JSX is compiled to string templates when a file is saved, each thread of the server keeps an engine per website with its code loaded, and a page reads its data next to the database. A page of a hundred rows renders in a tenth of a millisecond of JavaScript.

On top of that, the server keeps whole pages.

## Pages kept by the server

```ts
export const config: PageConfig = {
    cache: {
        maxAge: 60,                 // kept 60 seconds
        staleWhileRevalidate: 300,  // then sent for 300 more while one request makes it anew
        scope: 'public',            // one page for every anonymous visitor
        tags: ['products'],         // dropped by ctx.revalidate('products')
        query: ['page', 'sort'],    // the parts of the query which make another page
    },
};
```

| `scope` | Kept for | A signed-in visitor |
|---|---|---|
| `'public'` | Every anonymous visitor : one page | Gets a page of its own, never one kept for others |
| `'user'` | Each visitor : one page per visitor | Gets its own kept page |
| `'none'` (default) | Nobody | |

- `cache` of a layout applies to the pages inside it ; `cache` of `site.config.ts` to every page which says nothing.
- A page is kept under its website, the version of the website, its path, the parts of its query (`query`, all of them by default, in their order), and the visitor for `'user'`. **A save of the website drops every kept page** : a new version is a new key.
- The answer says what happened in `x-am-cache` : `MISS` (made and kept), `HIT` (sent as kept), `BYPASS` (not kept, see below).
- The preview of the panel never keeps pages.
- What is kept has a size in all (`ssr.cacheMb` of the server, 64 MiB by default) : past it, the pages used longest ago go. A page larger than a quarter of it is not kept.

## Dropping kept pages

**pages/api/products.ts**

```ts
export async function POST(ctx: PageContext) {
    // ... a product is saved ...
    await ctx.revalidate('products');
    return { saved: true };
}
```

`ctx.revalidate(...tags)` drops the pages of these tags in this server. A pull of git and a save in the panel drop every page of the website on every server.

## What is never kept for everyone

A page kept for everyone shows nothing of its visitor. The server keeps none which :

- was made for a request with messages of `ctx.flash` ;
- set cookies, or keeps a message for the next page ;
- **read what differs from one visitor to the next** : `ctx.cookies`, `ctx.headers`, `ctx.ip`, `ctx.locale` or `ctx.csrf`. Such a page is sent (`x-am-cache: BYPASS`), not kept ;
- did not answer `200`.

What a loader writes into a page is up to it : never put a value of `ctx.user` into a page with `scope: 'public'` — a signed-in visitor never gets a public page, but keep the rule anyway.

> **Tip : A count in the header without losing the cache**
>
> The shop template shows the count of the cart in its header with a script, from a cookie which holds no secret : its pages stay the same for every anonymous visitor, and the server keeps them.

## What browsers keep

- A page kept for everyone is sent with `cache-control: no-cache` : browsers ask again (the page holds the CSRF token of its visitor), the server answers from its cache.
- A page per visitor : `private, max-age=…`. A page of a signed-in visitor otherwise : `private, no-store`.
- A JSON endpoint with `scope: 'public'` which read nothing of its visitor : `public, max-age=…, stale-while-revalidate=…` — a CDN may keep it.
- Public files with the hash of their content (`asset('/app.css')`) : `immutable`, a year. Without it : an `ETag`, and `304` when nothing changed.

## The settings of the server

| Setting | Default | What it is |
|---|---|---|
| `ssr.threads` | the cores | Threads which render pages |
| `ssr.enginesPerThread` | 64 | Websites a thread keeps loaded |
| `ssr.memoryMb` | 64 | Memory of an engine |
| `ssr.cpuMs` | 2000 | Time of the code of one render |
| `ssr.timeoutMs` | 30000 | Time of one render in all, the waits for data included |
| `ssr.cacheMb` | 64 | Size of the pages kept, 0 for none |

See [API Maker configuration](https://docs.apimaker.dev/v4/docs/am-resources/api-maker-configurations.html#ssr).
