# Remix without limits \(historical\)

**Published:** March 22, 2023 | **Authors:** Nathan Rajlich, Ethan Arrowood | **Category:** Community

*Deploy and scale Remix apps of any size and complexity\.*

---

We are excited to announce our **advanced Remix integration**, including support for:

> **Note:** This post is historical. Product names and runtime guidance may have changed. For new projects, use [Vercel Functions](https://vercel.com/docs/functions) with the Node.js runtime and [Fluid compute](https://vercel.com/docs/fluid-compute). Use [Routing Middleware](https://vercel.com/docs/routing-middleware) for request-time routing before a response completes.

- **Streaming SSR:** Dynamically stream content with both Node.js and Edge runtimes
- **API Routes:** Easily build your serverless API with Remix and a route `loader`
- **Advanced Caching:** Use powerful cache headers like `stale-while-revalidate`
- **Data Mutations:** Run `actions` inside Vercel Functions

## Remixing Adapters

[Remix](https://remix.run/) is a server-rendered React framework with a focus on Web fundamentals. Since the Remix request handler is built on the [Web Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), it can be *adapted* to work with any deployment provider.

With the new advanced Remix integration for Vercel (`@vercel/remix`), no adapter is required to get started. Vercel now supports the most lightweight, powerful Remix integration, including no `server.js` file or custom `vercel.json` configuration needed.

This integration has been designed for use in our serverless environment, including support for runtime-specific build outputs at the time.

We've abstracted away runtime-specific needs, like how to handle cookies or streaming in different environments, and made it easily consumable. To take advantage of this, instances of `@remix-run/node` can be replaced with `@vercel/remix`.

We are collaborating with the Remix team to [contribute changes back upstream](https://github.com/remix-run/remix/pulls/TooTallNate) and help make the Remix build outputs more modular.

## Server-rendering with multiple runtimes

Until today, deploying Remix applications meant choosing between **two different runtimes for the entire application**: choosing all Node.js, or all Web/Edge-oriented runtimes.

With Vercel's advanced Remix support, applications can now choose their runtime on a per-route basis. This means you get the best parts of both Node.js and Web APIs – all in one application on one platform.

For current Remix projects on Vercel, use the Node.js runtime by default and configure Vercel Functions for backend logic.

## Advanced Caching

Vercel supports caching `loader` responses using our Edge Network Cache by providing `cache-control` headers to a given route. This includes support for newer [caching headers](https://vercel.com/docs/cdn-cache) like `stale-while-revalidate` and `stale-if-error`.

For example, the following `headers` tell Vercel:

- If a request is repeated within the next second, the previously cached value is still fresh.
- If the request is repeated between 1 and 60 seconds later, the cached value will be marked as stale but still shown.
- In the background, a revalidation will be made to populate the cache with a fresh value from the `loader`.

```jsx
export function headers() {
  return {
    "Cache-Control": "s-maxage=1, stale-while-revalidate=59",
  };
}
```

You can add further resiliency using the `stale-if-error` header. This tells the Vercel Edge Cache to reuse a stale response if the `loader` produces an error. For example, if you are trying to fetch data from a database or CMS and there’s a period of downtime, your site would *not* go down when the `loader` throws an error.

```javascript
export function headers() {
  return {
    "Cache-Control": "s-max-age=2592000, stale-while-revalidate=86400, stale-if-error=604800",
  };
}
```

This `cache-control` value uses a `max-age` value of 30 days, a `stale-if-revalidate` value of 1 day, and a `stale-if-error` value of 7 days.

[Jenna Smith](https://twitter.com/jjenzz) has created a [fantastic package](https://github.com/jjenzz/pretty-cache-header) to make working with `cache-control` values easier called `pretty-cache-header`. For example, the previous example would become:

```javascript
import { cacheHeader } from 'pretty-cache-header';
export function headers() {
  return {
    "Cache-Control": cacheHeader({
      sMaxAge: '30days',
      staleWhileRevalidate: '1day',
      staleIfError: '7days'
    })
  };
}
```

## Streaming SSR on Vercel

Vercel's Remix integration has support for streaming SSR, including usage with both Edge and Node.js runtimes.

By default, the Vercel integration will automatically add `app/entry.server.tsx`, if not defined, which is configured for streaming. Existing Remix projects can also adopt the following entry file to stream isomorphically:

**app/entry.server.tsx**
```tsx
import { handleRequest } from '@vercel/remix';
import { RemixServer } from '@remix-run/react';
import type { EntryContext } from '@vercel/remix';
export default function (
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  const remixServer = <RemixServer context={remixContext} url={request.url} />;
  return handleRequest(
    request,
    responseStatusCode,
    responseHeaders,
    remixServer
  );
}
```

Powerful Remix features like `defer()` and `<Await>`, built on top of React 18 and `Suspense`, are now supported in both runtimes. For example, [in our demo](https://remix-on-the-edge.vercel.app/), we're able to simulate a throttled network by delaying our `Promise` by one second. Then, we can use the deferred result inside our React component.

```javascript
import { Suspense } from 'react';
import { Await, useLoaderData } from '@remix-run/react';
export async function loader({ request }) {
  const version = process.versions.node;

  return defer({
    version: sleep(version, 1000),
  });
}
function sleep(val, ms) {
  return new Promise((resolve) => setTimeout(() => resolve(val), ms));
}
export default function App() {
  const { version } = useLoaderData();
  
  return (
    <Suspense fallback={'Loading…'}>
      <Await resolve={version}>
        {(version) => <strong>{version}</strong>}
      </Await>
    </Suspense>
  );
}
```

With Vercel, your Remix application is fast globally. With a cache `MISS`, we frequently see under 100ms latency for a dynamic server-rendered page.

## Try Remix on Vercel today

Remix on Vercel uses framework-defined infrastructure so your application can take advantage of Vercel Functions, caching, and streaming. With [framework-defined infrastructure](https://vercel.com/blog/framework-defined-infrastructure), your Remix application automatically takes advantage of the best infrastructure primitives.

We're continuing to invest in further improvements to Remix on Vercel and we'd love to hear your feedback on what you want to see.

---

**More posts:** [View all blog posts](https://vercel.com/blog/sitemap.md) | [Changelog](https://vercel.com/changelog/sitemap.md)