Skip to main content
Bun ships a built-in HTTP server powered by uWebSockets. It handles ~160,000 requests/second on Linux — roughly 2.5x Node.js — with zero dependencies.

Basic server

The fetch handler receives a standard Request and must return a Response or Promise<Response>.
Port defaults to $BUN_PORT, $PORT, or $NODE_PORT when the port option is omitted. You can also set it via bun --port=4000 server.ts.

Routing

Use the routes option (requires Bun v1.2.3+) to define path-based handlers with static paths, route parameters, and wildcards.

Route precedence

Routes are matched from most to least specific:
  1. Exact routes (/users/all)
  2. Parameter routes (/users/:id)
  3. Wildcard routes (/users/*)
  4. Global catch-all (/*)

Type-safe route parameters

TypeScript infers parameter names directly from the route string literal:

Query parameters

Parse query parameters from the request URL:

Reading request bodies


JSON responses

Use Response.json() to serialize data with the correct Content-Type header:

Streaming responses

Return a ReadableStream or an async generator to stream data to the client:
The idle timeout (default: 10 seconds) applies to streaming responses. If your stream goes quiet for longer than idleTimeout, the connection closes mid-stream. Disable it per-request with server.timeout(req, 0).

Static file serving

Return a BunFile as the response body to serve files from disk. Bun uses the sendfile(2) syscall for zero-copy transfers when possible.

TLS / HTTPS

Enable HTTPS by providing key and cert in the tls option. Bun uses BoringSSL under the hood.
key and cert accept a string, BunFile, Buffer, TypedArray, or an array of any of those.

Error handling

Use the error handler to catch unhandled errors thrown inside fetch or route handlers and return a custom Response:
Enable development: true to display a full error page with stack traces in the browser during development:

Server lifecycle

server.stop()

Stop the server from accepting new connections. By default it waits for in-flight requests to finish; pass true to close all connections immediately.

server.reload()

Hot-swap fetch, error, and routes handlers without restarting the process or dropping connections:

Per-request controls

server.timeout(req, seconds)

Override the idle timeout for a single request. Pass 0 to disable it entirely — useful for Server-Sent Events and long-running streams.

server.requestIP(req)

Get the client’s IP address and port:
Returns null for Unix socket connections or closed requests.

Unix domain sockets

Listen on a Unix socket instead of a TCP port:

export default syntax

Instead of calling Bun.serve() explicitly, you can export default a server config object. Bun detects the fetch property and starts the server automatically:

Practical example: REST API


Reference