The deno serve command runs a JavaScript or TypeScript file as an HTTP server.
Usage
deno serve [OPTIONS] [SCRIPT]
Description
The serve command is optimized for running HTTP servers. It automatically handles multiple workers for improved performance and provides special handling for modules that export a default object with a fetch handler.
Flags
The port to listen on (default: 8000)
The host to listen on (default: 0.0.0.0)
Run multiple server instances in parallel for better performance
Open a browser window to the server URL after starting
Watch for file changes and restart the server
Enable Hot Module Replacement (requires —watch)
Do not clear the screen when restarting in watch mode
Permission Flags
Allow network access. Usually required for servers
Allow file system read access
Allow file system write access
Other Runtime Flags
Specify the configuration file
Disable automatic loading of the configuration file
Check the specified lock file
Enables or disables the use of a local node_modules folder
Your server module should export a default object with a fetch handler:
export default {
fetch(req: Request): Response | Promise<Response> {
return new Response("Hello, World!");
},
};
Or using the Deno.ServeDefaultExport type:
export default {
fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/") {
return new Response("Home page");
}
return new Response("Not found", { status: 404 });
},
} satisfies Deno.ServeDefaultExport;
Examples
Basic server
Create a simple server (server.ts):
export default {
fetch(req) {
return new Response("Hello from Deno!");
},
};
Run it:
deno serve --allow-net server.ts
Custom port and host
deno serve --port 3000 --host localhost server.ts
With file system access
Serve static files:
deno serve --allow-net --allow-read server.ts
Watch mode
Automatically restart on file changes:
deno serve --watch --allow-net server.ts
Hot Module Replacement
Enable HMR for faster development:
deno serve --watch --hmr --allow-net server.ts
Parallel workers
Run multiple workers for better performance:
deno serve --parallel --allow-net server.ts
Open browser automatically
deno serve --open --allow-net server.ts
Complete development setup
deno serve --watch --hmr --parallel --port 3000 --allow-net --allow-read server.ts
Routing Example
Handle different routes:
export default {
fetch(req) {
const url = new URL(req.url);
switch (url.pathname) {
case "/":
return new Response("Home page");
case "/about":
return new Response("About page");
case "/api/users":
return Response.json({ users: ["Alice", "Bob"] });
default:
return new Response("Not found", { status: 404 });
}
},
};
Using URLPattern
Match dynamic routes:
const userPattern = new URLPattern({ pathname: "/users/:id" });
const staticPattern = new URLPattern({ pathname: "/static/*" });
export default {
fetch(req) {
const url = new URL(req.url);
const userMatch = userPattern.exec(url);
if (userMatch) {
const userId = userMatch.pathname.groups.id;
return new Response(`User ID: ${userId}`);
}
if (staticPattern.test(url)) {
return serveStaticFile(req);
}
return new Response("Not found", { status: 404 });
},
};
Use parallel workers
For CPU-intensive workloads:
deno serve --parallel --allow-net server.ts
Enable caching
Use Deno’s built-in caching:
const cache = await caches.open("my-cache");
export default {
async fetch(req) {
const cached = await cache.match(req);
if (cached) return cached;
const response = await generateResponse(req);
await cache.put(req, response.clone());
return response;
},
};
Environment Variables
Access environment variables:
export default {
fetch(req) {
const port = Deno.env.get("PORT") || "8000";
return new Response(`Server configured for port ${port}`);
},
};
Run with environment variables:
PORT=3000 deno serve --allow-net --allow-env server.ts
See Also