# Advanced concepts

These concepts explain why Rebask stores resume state, rerenders part of the tree on a cache hit,
and namespaces cache entries by deployment.

## What a resume stores

A PPR shell is server-rendered HTML plus state that lets Rebask finish the page later. During
prerendering, React's Fizz renderer returns two things:

- A prelude: the HTML that is already complete, including Suspense fallbacks.
- A postponed state: where the render stopped at a `<Suspense>` boundary and the structure React
  needs to replay.

Rebask adds a third piece: the [`"use cache"`](./caching/server-components.md#use-cache) and
[`durableCache`](./caching/server-components.md#durablecache) entries the shell read. That map is
serialized with the postponed state and stored in the
[page cache entry](./caching/page-caching.md).

The shell is served long after it was rendered, but the RSC payload that hydrates it is rendered per
request. When the shell is resumed, Rebask reads the pinned entries before the live cache, so the
cached HTML and the new payload use the same values. Without those entries, a cache change between
build and request could leave the resumed HTML with the old value while the new payload used the new
one.

At request time Rebask:

1. Looks up the shell and parses its resume state.
2. Pins the stored cache entries in the request context.
3. Renders the [RSC tree](#why-the-rsc-tree-renders-again) for this request.
4. Calls React's `resume()` to stream the dynamic holes into the shell.
5. Promotes the result to a more specific shell or Complete HTML when possible.

To learn more, see [PPR](./rendering/ppr.md), [Page Caching](./caching/page-caching.md), and
[Cache Handler](./caching/cache-handler.md).

## Why the RSC tree renders again

React can resume an HTML render, but it cannot resume the server execution that produced the RSC
data.

Fizz, the HTML renderer, can stop at a `<Suspense>` boundary and record enough state to continue
later. That is what `resume()` consumes. The postponed state is a replayable render state, not a
serialized promise or call stack.

Flight, the RSC format, is a serializable description of a component tree. It has no equivalent
`resume()` for the server render. It can stream promise chunks to the client, but the server-side
promise continuation and its closed-over state are gone once the request ends.

So Rebask rerenders the RSC tree to produce a fresh Flight payload, then resumes the existing HTML
from the postponed state. Only the postponed part streams. Values the shell already read from
`"use cache"` come from the pinned entries instead of being fetched again, but components rerun and
work inside the postponed part still runs.

This is also why request I/O can't be baked into a shell:
[`headers()`](./server-runtime-apis.md#headers), [`cookies()`](./server-runtime-apis.md#cookies), and
other request reads produce values that only exist for one request. Put them under `<Suspense>` so
PPR can [resume them](./rendering/ppr.md#suspense-and-dynamic-work). Outside `<Suspense>`, the route
has no static shell. See [Server Runtime APIs](./server-runtime-apis.md).

## Deployment IDs and cache namespaces

A production build gets a new `deploymentId` by default. Page, RSC, and `"use cache"` cache keys
include it. `durableCache` keys do not, because those values are meant to outlive a deployment.

The old entries are not deleted when you deploy. Their keys become unreachable, and the cache
handler removes them by lifetime or eviction. That is why a new build looks like an empty cache
without Rebask flushing it.

Rebask generates a new [`deploymentId`](./configuration.md#rebask-deploymentid) for each production
build. Override it only when an external system supplies a unique ID for each deployment. Use
[`durableCache`](./caching/server-components.md#durablecache) for data that must survive builds. See
[Server Cache keys](./caching/introduction.md#server-cache-keys) for the full key table.

## Internal headers

Rebask uses request and response headers to coordinate the router, the server, and platform
adapters.

> These headers are not public APIs and can change between releases. Treat the mas implementation
> details

| Header                   | Direction | Purpose                                                                                                                                                                                             |
| ------------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x-rebask-tree`          | Request   | Ask for the route tree JSON used by client navigations and deployment checks.                                                                                                                       |
| `x-rebask-shell`         | Request   | Ask for a route segment's Flight shell.                                                                                                                                                             |
| `x-rebask-tail`          | Both      | Identify a shell by `byteLength:sha256`. The server echoes it only when the shell matches.                                                                                                          |
| `x-rebask-trailer`       | Response  | Nonce separating the RSC payload from its trailing search-param record. The record has to wait until the render ends, and the client needs it to decide whether a cached segment is still reusable. |
| `x-rebask-cache`         | Response  | Origin cache outcome: `HIT`, `STALE`, or `MISS`. Absent when the adapter owns page caching.                                                                                                         |
| `x-rebask-prerender`     | Response  | `1` when serving a cached shell plus streamed dynamic content.                                                                                                                                      |
| `x-rebask-deployment-id` | Response  | Deployment id of the server that produced the response.                                                                                                                                             |
| `x-rebask-resume`        | Request   | Marks a POST as a resume. The adapter validates the platform credential, then Rebask reads the resume state from the request body.                                                                  |
| `x-rebask-fill`          | Request   | Tells Rebask what a platform cache fill should render: `html` for a page or shell, `rsc` for an RSC payload. Only the adapter sets it.                                                              |
| `x-rebask-pathname`      | Request   | Platform-supplied original pathname, stripped before application code.                                                                                                                              |
| `x-rebask-proxy-only`    | Both      | Development-only marker for a request that only the proxy should answer.                                                                                                                            |

Only the three diagnostic headers in [DevTools](./devtools.md#diagnostic-headers) are meant for
inspection. `x-rsc-action` belongs to React's Flight protocol, not Rebask. Platform adapters may add their
own transport headers and route suffixes. See [Vercel](./production/vercel.md) for its request flow.

### `x-rebask-trailer`

If a segment reads [`searchParam("sort")`](./server-runtime-apis.md#searchparamname), the response body ends with
`\r\n--<nonce>\r\n{"used":{"sort":"price"}}`, where the nonce is the header value. The client
splits there, decodes only the RSC bytes, and records that the segment depends on `sort=price`:

::search-param-reuse
::

[Shells](./caching/segment-caching.md#shells-and-tails) leave search params out so one shell can serve
any query string for a path it matches. When
the shell resumes, the client caches the resumed segment by the params the render read. A different
`sort` gets a separate entry, while an unrelated `utm` change reuses the same one. The trailer
reports which params were read.

The search params are only known when rendering ends, so they are appended. Sending them as a
response header would require buffering the RSC stream.
