---
title: Warp
---
In Svelte, when you want to render asynchronous content data on the server, you can simply `await` it. This is great! However, it comes with a pitfall: when hydrating that content on the client, Svelte has to redo the asynchronous work, which blocks hydration for however long it takes:
```svelte
{user.name}
```
That's silly, though. If we've already done the hard work of getting the data on the server, we don't want to get it again during hydration on the client. `Warp` is a low-level API built to solve this problem. You probably won't need this very often — it will be used behind the scenes by whatever datafetching library you use. For example, it powers [remote functions in SvelteKit](/docs/kit/remote-functions).
A `Warp` is a [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) whose contents are sent from the server to the client. Anything you add to it while rendering on the server is serialized into the `head` returned from `render`, and is available in the `Warp` with the same id on the client. To fix the example above:
```svelte
{user.name}
```
This API can also be used to provide access to random or time-based values that are stable between server rendering and hydration. For example, to get a random number that doesn't update on hydration:
```ts
import { Warp } from 'svelte';
const warp = new Warp('my-app');
const rand = warp.getOrInsertComputed('random', () => Math.random());
```
On the client, a `Warp` behaves like any other `Map` — values you add to it stay there until you remove them with `delete` or `clear`. On the server, each key can only be set once, and values can't be removed, since they may already be in use or on their way to the client. For the same reason, treat values as immutable once they've been added to a `Warp`.
Keys can be strings, numbers, booleans or bigints. If you're a library author, use your package name as the `Warp`'s id, so that it doesn't conflict with other libraries:
```js
import { Warp } from 'svelte';
const warp = new Warp('my-datafetching-library');
```
## Serialization
All data added to a `Warp` must be serializable. But this doesn't mean you're limited to JSON — Svelte uses [`devalue`](https://npmjs.com/package/devalue), which can serialize all sorts of things including `Map`, `Set`, `URL`, and `BigInt`. Check the documentation page for a full list. You can also fearlessly use promises:
```svelte
{await promises.one}
{await promises.two}
```
If a promise rejects, the promise on the client will reject too. The rejection reason is passed through the [`transformError`](svelte-server#render) option of `render` first, so that sensitive information doesn't leak to the client — if you don't provide `transformError`, the client receives a generic error instead.
To serialize other kinds of values, pass a `replacer` to `render`. It works like the replacer for devalue's [`uneval`](https://github.com/sveltejs/devalue#custom-types), receiving each value and a `js` tag that you can use to return the JavaScript that recreates it on the client:
```js
/// file: server.js
// @noErrors
import { render } from 'svelte/server';
import App from './App.svelte';
import { Vector } from './vector.js';
// ---cut---
const { head, body } = await render(App, {
replacer: (value, js) => {
if (value instanceof Vector) {
return js`new Vector(${value.x}, ${value.y})`;
}
}
});
```
## Using `Warp` outside components
`Warp` can only be used on the server while rendering. If you need to add values before the render starts — for example, while loading data for a page — wrap the work in `withWarp`. A `render` inside `withWarp` will serialize everything added to `Warp` instances inside it:
```js
/// file: server.js
// @noErrors
import { render, withWarp } from 'svelte/server';
import { Warp } from 'svelte';
import App from './App.svelte';
import { getUser } from 'my-database-library';
// ---cut---
const warp = new Warp('my-app');
const { head, body } = await withWarp(async () => {
const user = await warp.getOrInsertComputed('user', () => getUser());
return render(App, { props: { user } });
});
```
`withWarp` also accepts a `replacer`, which is used for any values the `replacer` passed to `render` doesn't handle. Each `withWarp` can only contain one `render`.
## Streaming
By default, when the server encounters a [``](svelte-boundary) with a `pending` snippet, it renders the `pending` snippet and nothing else. The client then renders the boundary's contents itself, which means any data they need only starts loading once the page has hydrated.
With the `experimental.streaming` compiler option, the server also starts rendering the boundary's contents in the background (discarding the output). Any values they add to a `Warp` are sent to the client as soon as they're available, so the client can use them instead of loading the data again:
```js
/// file: svelte.config.js
export default {
compilerOptions: {
experimental: {
async: true,
streaming: true
}
}
};
```
Values that have already resolved by the time the HTML is rendered are included in the `head`, as usual. The rest are streamed via the `tail` of the render result, which contains `