Type something to search...
What are Astro adapters and which one should you choose?

What are Astro adapters and which one should you choose?

An Astro adapter is an integration that builds the server part of your project for a specific runtime, such as Node.js, Vercel Functions, Netlify Functions or Cloudflare Workers. Without one, Astro can only produce static HTML. With one, it can render pages and endpoints on demand, run actions and server islands, and use sessions. To choose, match the adapter to where you'll deploy: @astrojs/node for your own server or a container, @astrojs/vercel for Vercel, @astrojs/netlify for Netlify and @astrojs/cloudflare for Cloudflare Workers. If your whole site is prerendered and you don't need host-specific features, you don't need an adapter at all.

Adapters are easy to add but easy to misunderstand. They don't change how you write pages, yet they decide what your dist folder contains, how environment variables reach your code and which platform services, such as image optimisation or session storage, are wired up for you. In this article you'll learn what an adapter does, when you need one, how to add it, what each official adapter produces, how they differ in the features they configure, and a short decision guide for picking one.

What an Adapter Actually Does

During astro build, Astro compiles your on-demand routes into server code. That code needs an entry point that the host knows how to run, and every host expects something different:

  • A Node.js server expects a JavaScript file it can start with node.
  • Vercel expects its Build Output API format in a .vercel/output folder.
  • Netlify expects functions in a .netlify folder and static files in a publish directory.
  • Cloudflare Workers expects a Worker script plus a Wrangler configuration describing its bindings.

The adapter fills that gap. It wraps Astro's request handler in the shape the platform expects, writes the platform's configuration files and arranges static and server output into the right folders. It can also enable platform services: an image CDN, a session store or edge middleware.

Your page code stays the same. A page with export const prerender = false works identically with all four official adapters, which is what makes switching hosts realistic.

When You Need an Adapter

You need an adapter when your project uses anything that runs at request time:

  • On-demand rendered pages or endpoints: any route with export const prerender = false, or a project with output: 'server'.
  • Server islands: components with server:defer need a server to render them.
  • Actions: Astro Actions run on the server and need an adapter.
  • Sessions: the Sessions API stores data on the server between requests.

You may also want one for a fully static site if you use a host feature that depends on it. The Netlify adapter enables Netlify Image CDN and translates the redirects in your Astro config into a _redirects file. The Vercel adapter can turn on Vercel Image Optimization and Web Analytics.

If none of that applies, skip the adapter. A static Astro site is a folder of HTML, CSS and JavaScript that any host can serve. The trade-offs between the two approaches are covered in static vs on-demand rendering.

How to Add an Adapter

The quickest way is astro add, which installs the package and edits your config:

npx astro add node
npx astro add vercel
npx astro add netlify
npx astro add cloudflare

You only run one of these. To add an adapter manually, install the package and set the adapter key:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel';

export default defineConfig({
  adapter: vercel(),
});

A project can have only one adapter. Adding it doesn't make your pages dynamic on its own: every page is still prerendered until you opt a route out with export const prerender = false or set output: 'server'. That workflow is explained in mixing prerendered and on-demand pages.

Some adapters add more than the config line. Running astro add cloudflare in an Astro 7 project also installs wrangler, adds a generate-types script that runs wrangler types, creates a wrangler.jsonc file and adds worker-configuration.d.ts to your tsconfig.json.

What Each Official Adapter Produces

To compare them, the same small project was built with each adapter. It had four prerendered pages, one on-demand page at /dashboard and one on-demand endpoint at /api/time. All four adapters used the current versions at the time of writing (@astrojs/node 11.1.9, @astrojs/vercel 11.0.16, @astrojs/netlify 8.2.10 and @astrojs/cloudflare 14.4.2, with Astro 7.4.2).

@astrojs/node

The Node adapter writes static files to dist/client/ and a server to dist/server/entry.mjs:

dist/client/index.html
dist/client/about/index.html
dist/server/entry.mjs
dist/server/chunks/dashboard_mnysE5wV.mjs
dist/server/chunks/time_C_zo6Q6k.mjs

It has two modes. standalone builds a complete HTTP server that also serves the static files, and you start it with node ./dist/server/entry.mjs. middleware builds a handler you mount inside an existing Express or Fastify app. You can change the host and port at runtime with the HOST and PORT environment variables.

// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  adapter: node({ mode: 'standalone' }),
});

This is the adapter for a VPS, a container platform or anywhere else you control the process. It's also the one to use for deploying with Docker.

@astrojs/vercel

The Vercel adapter produces Vercel's Build Output API layout:

.vercel/output/config.json
.vercel/output/static/index.html
.vercel/output/static/about/index.html
.vercel/output/functions/_render.func/.vc-config.json

Static pages go to .vercel/output/static, and all on-demand routes are bundled into a single function called _render. The generated config.json serves files first and sends the dynamic routes to that function. The function's .vc-config.json picks a Node.js runtime; the build warned that the local Node.js 26 isn't supported by Vercel Functions and used nodejs24.x instead.

Vercel-specific options include isr for Incremental Static Regeneration, imageService for Vercel Image Optimization, webAnalytics, maxDuration, skewProtection and middlewareMode: 'edge' to run Astro middleware as an edge function. See deploying to Vercel for the full walkthrough.

@astrojs/netlify

The Netlify adapter leaves static files in dist/ and writes functions to .netlify/:

dist/index.html
dist/about/index.html
.netlify/v1/config.json
.netlify/v1/functions/ssr/ssr.mjs
.netlify/v1/edge-functions/

The ssr function handles every on-demand route, with preferStatic: true so existing files are served first. By default, the adapter also uses Netlify Image CDN for Astro's image components and Netlify Blobs for sessions. Options include cacheOnDemandPages, imageCDN, middlewareMode: 'edge', includeFiles, excludeFiles and devFeatures. See deploying to Netlify.

@astrojs/cloudflare

The Cloudflare adapter targets Cloudflare Workers and splits the output into dist/client/ and dist/server/:

dist/client/index.html
dist/client/_headers
dist/client/.assetsignore
dist/server/entry.mjs
dist/server/wrangler.json

The build generates a complete dist/server/wrangler.json with an ASSETS binding for the static files, a SESSION KV binding and an IMAGES binding, and wrangler deploy picks it up automatically. Since @astrojs/cloudflare v13, which came with Astro 6, astro dev and astro preview run your code in Cloudflare's workerd runtime instead of Node.js, so local behaviour matches production closely. The same release removed support for Cloudflare Pages. See deploying to Cloudflare for what that means in practice.

How the Adapters Compare

NodeVercelNetlifyCloudflare
Package@astrojs/node@astrojs/vercel@astrojs/netlify@astrojs/cloudflare
RuntimeAny Node.js processVercel Functions (Node.js)Netlify FunctionsCloudflare Workers (workerd)
Build outputdist/client, dist/server.vercel/outputdist, .netlifydist/client, dist/server
Default session storageLocal filesystemNone, configure a driverNetlify BlobsWorkers KV
Image optimisationAstro's default (Sharp)Vercel Image Optimization with imageService: trueNetlify Image CDN by defaultCloudflare Images binding by default
Runtime env varsprocess.envprocess.envprocess.envcloudflare:workers env or astro:env
Edge middleware optionNomiddlewareMode: 'edge'middlewareMode: 'edge'Runs at the edge already

The session row matters more than it looks. If you use the Sessions API on Vercel, you must configure a storage driver yourself, for example Redis. On the other three, it works out of the box. If you don't use sessions at all, session: false in your Astro config stops the adapter from setting up storage and keeps the session runtime out of your bundle.

Which Adapter Should You Choose?

Start from where the site will run, then check that the platform suits what your app does.

  • You want full control or already have servers: use @astrojs/node in standalone mode behind a reverse proxy, or package it in a container. You manage scaling, TLS and uptime yourself, but there are no platform limits on execution time or request size beyond what you configure.
  • You want Git-based deploys with preview URLs and minimal setup: Vercel and Netlify both detect Astro automatically. Choose based on the platform features you want (ISR and skew protection on Vercel; Image CDN, Blobs and Netlify Forms on Netlify) and on pricing for your traffic.
  • You want code running close to users worldwide with Cloudflare storage: use @astrojs/cloudflare. KV, D1, R2, Durable Objects and Workers AI are available as bindings. Check that your dependencies work in workerd, which doesn't support every Node.js API and doesn't run CommonJS code in the new development setup.
  • You already have an Express or Fastify app: use @astrojs/node in middleware mode and mount Astro inside it.

There are community adapters for other runtimes in the Astro integrations directory. Check their maintenance status and Astro version support before relying on one, because adapters depend on internal APIs that change between major versions.

Switching Adapters Later

Because page code doesn't depend on the adapter, switching is mostly a config change. Watch for the places where platform code does leak in:

  1. Environment variables: on Cloudflare, runtime variables come from cloudflare:workers or astro:env, not process.env. Using astro:env everywhere makes this portable, because its getSecret() implementation is provided by the adapter.
  2. Platform objects in locals: Astro.locals.netlify.context, Astro.locals.cfContext and Vercel's edge context only exist on their own platforms.
  3. Node.js APIs: code that reads files with node:fs at request time works on Node but not on Workers.
  4. Session drivers and image services: the defaults change with the adapter, so data stored in one platform's session store won't follow you.

Search your code for these before switching, then rebuild and test with the new adapter's local preview.


FAQ: Astro Adapters

No. A fully prerendered site needs no adapter and can be deployed to any static host. Add one only if you use on-demand rendering, actions, server islands or sessions, or if you want a host feature that the adapter enables, such as Netlify Image CDN.

No. A project has a single adapter key in its config. If you need to deploy the same code to two platforms, build it twice with different configs, for example by reading an environment variable in astro.config.mjs to pick the adapter.

No. Adding an adapter only makes on-demand rendering available. Pages stay prerendered until you add export const prerender = false to a route or set output: 'server' in your config.

It depends on where your users are and what the route does. Prerendered pages are served as static files on every platform, so they're fast everywhere. For on-demand routes, the runtime location, cold starts and the distance to your database usually matter more than the adapter itself.

Not with current versions. The Cloudflare adapter dropped Pages support in v13, alongside Astro 6, and now targets Cloudflare Workers. A fully static Astro site with no adapter can still be uploaded to any static host, including Pages.

Set them in your host's dashboard or CLI for production, and in .env files locally. The Node adapter doesn't load .env files for you at runtime, so pass them to the process yourself. On Cloudflare, define them in your Wrangler config or as Worker secrets.


Conclusion

An Astro adapter is the bridge between your project and the runtime that will serve its dynamic parts. It decides what your build output looks like, writes the platform's configuration and switches on services like image optimisation and session storage, while your pages and endpoints stay exactly the same. If your site is fully static, you can skip adapters entirely.

When you do need one, choose by destination: Node for servers and containers, Vercel or Netlify for Git-driven managed hosting, and Cloudflare for Workers and its storage bindings. Keep platform-specific code to a minimum, prefer astro:env for configuration, and moving between adapters later becomes a config change rather than a rewrite.

Tags :
Share :

Related Posts

What are Astro Actions and how do they work?

What are Astro Actions and how do they work?

Astro Actions are type-safe backend functions that you define once on the server and then call from the browser as if they were ordinary async fu

Dive Deeper
How to build API endpoints in Astro?

How to build API endpoints in Astro?

To build an API endpoint in Astro, create a .js or .ts file in src/pages/ and export a function named after an HTTP method, such as GET or

Dive Deeper
How to add user authentication to an Astro site?

How to add user authentication to an Astro site?

To add user authentication to an Astro site, install an adapter so pages can run on demand, choose an auth library such as Better Auth or a h

Dive Deeper