How to Use Deno Deploy with Astro: Complete Guide
Step-by-step guide to integrating Deno Deploy with your Astro website.
Deno Deploy is a serverless platform for deploying JavaScript and TypeScript at the edge. It runs your code on Deno's global network of edge servers, meaning your Astro site responds from the nearest location to each visitor. The result is extremely low latency. Astro has a Deno adapter for on-demand (server-side) rendering, which makes this one of the smoother deployment integrations available.
What makes Deno Deploy different from traditional Node.js hosting is that it uses the Deno runtime instead of Node. This means native TypeScript support, a security-first permissions model, and Web Standard APIs built in. For on-demand rendered Astro sites, this translates to fast cold starts and efficient edge rendering.
One important note before you start. The adapter changed hands. The old @astrojs/deno package is no longer the path forward (its latest release, 5.0.1, declares a peer dependency on Astro ^3.1.4 and predates Astro 6). The adapter is now maintained by the Deno team and published as @deno/astro-adapter. Everything below uses the current package.
Prerequisites
- Node.js v22.12.0 or higher (Astro 6 dropped Node 18 and 20; odd-numbered versions like v23 are not supported)
- Deno installed locally (optional, for testing the built server:
curl -fsSL https://deno.land/install.sh | sh) - An Astro project (
npm create astro@latest), running Astro 6 (current release is 6.4.2) - A Deno Deploy account (free tier available)
- Your project in a GitHub repository (optional, for Git-connected deploys)
Installation
Install the current Astro Deno adapter. @deno/astro-adapter declares a peer dependency on astro: ^6.0.0, so make sure your project is on Astro 6.
npm install @deno/astro-adapter
If you work in a Deno-first toolchain, the adapter README shows the equivalent Deno command:
deno add npm:@deno/astro-adapter
Note: Even though you can develop with npm/Node locally, the Deno adapter builds an entry point that runs on the Deno runtime in production.
The adapter only matters for on-demand (server-side) rendering. A fully static Astro site does not need any adapter to deploy on Deno Deploy. See the static path in the deployment section below.
Configuration
Astro renders every route to static HTML by default. As the Astro docs put it, "By default, your entire Astro site will be prerendered, and static HTML pages will be sent to the browser." To render routes on demand you add an adapter and set output: 'server'.
Update your Astro config to use the Deno adapter:
// astro.config.mjs
import { defineConfig } from "astro/config";
import deno from "@deno/astro-adapter";
export default defineConfig({
output: "server",
adapter: deno(),
});
Important change from older guides: output: 'hybrid' no longer exists. It was removed in Astro 5, and static is the default. There is no third mode to pick. The correct pattern in Astro 6 is to set output: 'server' for an adapter-backed build, then keep most pages static with a per-route opt-in and render only the routes that need it on demand. The on-demand rendering docs state: when using output: 'server', "you can make individual pages static by adding export const prerender = true," and to render a single page on demand you add export const prerender = false at the top of that file.
The deno() adapter accepts a few options (per the adapter README): port (default 8085), hostname (default "0.0.0.0"), and start (a boolean controlling whether the generated entry script starts its own web server). If you set start: false, you import the exported handle function from the generated entry and wire it into your own Deno server.
Now connect your project to Deno Deploy. For a Git-connected project:
- Go to dash.deno.com and create a new project
- Connect your GitHub repository
- Set the entry point to
dist/server/entry.mjs - Set the build command to
npm run build
Alternatively, use the deployctl CLI. Install it from JSR (the previous deno.land/x install line is outdated):
# Install deployctl from JSR
deno install -gArf jsr:@deno/deployctl
# Deploy the built server entry
deployctl deploy ./dist/server/entry.mjs
Environment variables are set in the Deno Deploy dashboard under your project's settings:
# In Deno Deploy Dashboard > Settings > Environment Variables
SITE_URL=https://yourdomain.com
API_KEY=your-api-key
Basic Usage
With the Deno adapter configured, your Astro site works the same way during development. The differences only show up in production. Write your pages and components normally:
---
// src/pages/index.astro
import BaseLayout from "../layouts/BaseLayout.astro";
---
<BaseLayout title="Home">
<h1>Hello from the edge</h1>
<p>This page is served from the nearest Deno Deploy edge location.</p>
</BaseLayout>
Server-rendered API routes work as expected:
// src/pages/api/time.ts
import type { APIRoute } from "astro";
export const GET: APIRoute = async ({ request }) => {
const url = new URL(request.url);
return new Response(
JSON.stringify({
time: new Date().toISOString(),
region: Deno.env.get("DENO_REGION") || "unknown",
}),
{
status: 200,
headers: {
"Content-Type": "application/json",
"Cache-Control": "no-cache",
},
}
);
};
Dynamic pages with server-side data fetching. Opt the route out of prerendering with export const prerender = false:
---
// src/pages/posts/[slug].astro
export const prerender = false; // Server-rendered at request time
const { slug } = Astro.params;
const response = await fetch(`https://api.example.com/posts/${slug}`);
const post = await response.json();
if (!post) {
return Astro.redirect("/404");
}
---
<html>
<head><title>{post.title}</title></head>
<body>
<h1>{post.title}</h1>
<div set:html={post.content} />
</body>
</html>
The build and deploy process:
# Build locally
npm run build
# Deploy to Deno Deploy (happens automatically on git push if connected)
git add .
git commit -m "Deploy to edge"
git push origin main
If you prefer to run the built server locally before shipping, the adapter README shows the exact Deno command (the entry needs network, read, and env permissions):
deno run --allow-net --allow-read --allow-env ./dist/server/entry.mjs
Production Tips
Keep most pages static, opt routes into on-demand rendering. Not every page needs server rendering. Leave
staticas the default behavior, setoutput: 'server', and addexport const prerender = falseonly on the routes that genuinely need request-time rendering. This reduces edge compute and improves response times for static content.Take advantage of edge caching. Add appropriate
Cache-Controlheaders to your responses. Even on-demand pages can benefit from short cache durations (30-60 seconds) to reduce cold starts during traffic spikes.Use Deno's built-in KV store. Deno's platform includes Deno KV, a globally distributed key-value database. Use it for session storage, rate limiting, or caching API responses without adding an external database.
Monitor cold start times. Edge functions have cold starts. Keep your dependencies minimal and avoid importing large libraries in on-demand routes. The lighter your server bundle, the faster cold starts will be.
Set up preview deployments. Deno Deploy creates preview URLs for pull requests automatically when connected to GitHub. Use these for testing before merging to production.
Common Errors and Fixes
Cannot find package '@astrojs/deno'or a peer-dependency conflict on install. You are using the old, superseded package. Astro's own integration page notes the Deno adapter "was previously maintained by Astro but now is maintained by Deno directly," and advises existing users to migrate. Uninstall@astrojs/deno, install@deno/astro-adapter, and update the import inastro.config.mjstoimport deno from "@deno/astro-adapter";.output: 'hybrid'is an invalid option.hybridwas removed in Astro 5; there is no longer a hybrid mode. Use the defaultstaticfor fully prerendered sites, oroutput: 'server'with an adapter, then control rendering per route withexport const prerender = true | false. See the tracking issue withastro/astro#12278.An adapter is required for on-demand rendering. If you set
output: 'server'without an adapter, the build fails. Install@deno/astro-adapterand addadapter: deno()to your config.deno: command not foundwhen runningdeployctl deploy. The CLI is installed through Deno. Install it from JSR withdeno install -gArf jsr:@deno/deployctl(the olderdeno.land/x/deploy/deployctl.tsinstall line is outdated). Make sure Deno itself is installed and on your PATH first.PermissionDeniedwhen running the built entry locally. The Deno runtime denies access by default. The adapter's documented run command grants the needed scopes:deno run --allow-net --allow-read --allow-env ./dist/server/entry.mjs.Static deploys do not need the adapter. If your site is fully prerendered, do not add
output: 'server'or the adapter. Astro's deploy guide shows deploying the staticdistdirectory directly with Deno's file server (cd dist && deployctl deploy jsr:@std/http/file-server).Deno is not definedin client-side code.Deno.env.get()and otherDenoglobals only exist on the server. Keep them inside frontmatter or API routes, never in aclient:*component or a<script>that ships to the browser.
Alternatives to Consider
- Cloudflare Pages if you want edge deployment with a larger ecosystem of Workers, KV, and D1 database integrations.
- Vercel if you prefer a more established platform with built-in image optimization and middleware support for Astro.
- Netlify if you want edge functions with a broader feature set including forms, identity, and background functions.
Wrapping Up
Deno Deploy gives Astro sites true edge computing with minimal configuration thanks to the Deno-maintained adapter. Your on-demand pages render at the edge location closest to each visitor, which is hard to beat for global audiences. The free tier is generous enough for personal projects and small businesses, and the deployment workflow through GitHub is seamless. If you are building an on-demand Astro site and want the fastest possible response times worldwide, Deno Deploy is one of the most compelling options available. Just make sure you are on Astro 6 with @deno/astro-adapter, not the retired @astrojs/deno package.
Official Docs and Examples
- Astro deploy guide for Deno: docs.astro.build/en/guides/deploy/deno
- Astro Deno adapter integration page: docs.astro.build/en/guides/integrations-guide/deno
- Adapter source, README, and examples (Deno-maintained): github.com/denoland/deno-astro-adapter
@deno/astro-adapteron npm: npmjs.com/package/@deno/astro-adapter- Astro on-demand rendering (output modes, per-route
prerender): docs.astro.build/en/guides/on-demand-rendering - Deno Deploy frameworks reference: docs.deno.com/deploy/reference/frameworks
deployctlCLI on JSR: jsr.io/@deno/deployctl
Sources
Checked on 2026-05-29:
- Deploy your Astro Site with Deno (Astro Docs), official
output: 'server'config,deno install -gArf jsr:@deno/deployctlinstall,deployctl deploy ./dist/server/entry.mjs, and the static file-server deploy path. - @deno/astro-adapter integration page (Astro Docs), confirms the adapter is now maintained by Deno, not Astro, and that prior
@astrojs/denousers should migrate. - denoland/deno-astro-adapter (GitHub README),
deno add npm:@deno/astro-adapter, theimport deno from "@deno/astro-adapter"config, adapter options (portdefault 8085,hostnamedefault "0.0.0.0",start), anddeno run --allow-net --allow-read --allow-env ./dist/server/entry.mjs. - @deno/astro-adapter on the npm registry, version 0.5.2, peer dependency
astro: ^6.0.0. - @astrojs/deno on the npm registry, latest 5.0.1, peer dependency
astro: ^3.1.4, confirming the old package predates Astro 6. - astro on the npm registry, current Astro version 6.4.2.
- On-demand rendering (Astro Docs), static is the default, per-route
export const prerender = true | false. - using output 'hybrid' is an invalid option (withastro/astro#12278), confirms
hybridwas removed. - Frameworks (Deno Deploy reference), Deno Deploy framework support reference.
Related Articles
How to Use Algolia with Astro: Complete Guide
Step-by-step guide to integrating Algolia with your Astro website.
How to Integrate Auth0 with Astro: Complete Guide
Step-by-step guide to integrating Auth0 with your Astro website. Setup, configuration, and best practices.
How to Use AWS Amplify with Astro: Complete Guide
Step-by-step guide to integrating AWS Amplify with your Astro website.