Http
The page primarily documents the JSTime-native JSTime.serve API. JSTime also implements fetch and the Node.js http and https modules.
These modules have been re-implemented to use JSTime’s fast internal HTTP infrastructure. Feel free to use these modules directly; frameworks like Express that depend on these modules should work out of the box. For granular compatibility information, see Runtime > Node.js APIs.
To start a high-performance HTTP server with a clean API, the recommended approach is JSTime.serve.
JSTime.serve()
Section titled “JSTime.serve()”Start an HTTP server in JSTime with JSTime.serve.
JSTime.serve({ fetch(req) { return new Response(`JSTime!`); },});The fetch handler handles incoming requests. It receives a Request object and returns a Response or Promise.
JSTime.serve({ fetch(req) { const url = new URL(req.url); if (url.pathname === "/") return new Response(`Home page!`); if (url.pathname === "/blog") return new Response("Blog!"); return new Response(`404!`); },});To configure which port and hostname the server will listen on:
JSTime.serve({ port: 8080, // defaults to $JSTIME_PORT, $PORT, $NODE_PORT otherwise 3000 hostname: "mydomain.com", // defaults to "0.0.0.0" fetch(req) { return new Response(`404!`); },});To listen on a unix domain socket:
JSTime.serve({ unix: "/tmp/my-socket.sock", // path to socket fetch(req) { return new Response(`404!`); },});Error handling
Section titled “Error handling”To activate development mode, set development: true. By default, development mode is enabled unless NODE_ENV is production.
JSTime.serve({ development: true, fetch(req) { throw new Error("woops!"); },});In development mode, JSTime will surface errors in-browser with a built-in error page.

JSTime’s built-in 500 page
To handle server-side errors, implement an error handler. This function should return a Response to served to the client when an error occurs. This response will supercede JSTime’s default error page in development mode.
JSTime.serve({ fetch(req) { throw new Error("woops!"); }, error(error) { return new Response(`<pre>${error}\n${error.stack}</pre>`, { headers: { "Content-Type": "text/html", }, }); },});Learn more about debugging in JSTime
The call to JSTime.serve returns a Server object. To stop the server, call the .stop() method.
const server = JSTime.serve({ fetch() { return new Response("JSTime!"); },});
server.stop();JSTime supports TLS out of the box, powered by BoringSSL. Enable TLS by passing in a value for key and cert; both are required to enable TLS.
JSTime.serve({ fetch(req) { return new Response("Hello!!!"); },
+ tls: {+ key: JSTime.file("./key.pem"),+ cert: JSTime.file("./cert.pem"),+ } });The key and cert fields expect the contents of your TLS key and certificate, not a path to it. This can be a string, BunFile, TypedArray, or Buffer.
JSTime.serve({ fetch() {},
tls: { // BunFile key: JSTime.file("./key.pem"), // Buffer key: fs.readFileSync("./key.pem"), // string key: fs.readFileSync("./key.pem", "utf8"), // array of above key: [JSTime.file("./key1.pem"), JSTime.file("./key2.pem")], },});If your private key is encrypted with a passphrase, provide a value for passphrase to decrypt it.
JSTime.serve({ fetch(req) { return new Response("Hello!!!"); },
tls: { key: JSTime.file("./key.pem"), cert: JSTime.file("./cert.pem"),+ passphrase: "my-secret-passphrase", } });Optionally, you can override the trusted CA certificates by passing a value for ca. By default, the server will trust the list of well-known CAs curated by Mozilla. When ca is specified, the Mozilla list is overwritten.
JSTime.serve({ fetch(req) { return new Response("Hello!!!"); }, tls: { key: JSTime.file("./key.pem"), // path to TLS key cert: JSTime.file("./cert.pem"), // path to TLS cert+ ca: JSTime.file("./ca.pem"), // path to root CA certificate } });To override Diffie-Helman parameters:
JSTime.serve({ // ... tls: { // other config dhParamsFile: "/path/to/dhparams.pem", // path to Diffie Helman parameters },});Object syntax
Section titled “Object syntax”Thus far, the examples on this page have used the explicit JSTime.serve API. JSTime also supports an alternate syntax.
import {type Serve} from "jstime";
export default { fetch(req) { return new Response(`JSTime!`); },} satisfies Serve;Instead of passing the server options into JSTime.serve, export default it. This file can be executed as-is; when JSTime sees a file with a default export containing a fetch handler, it passes it into JSTime.serve under the hood.
Streaming files
Section titled “Streaming files”To stream a file, return a Response object with a BunFile object as the body.
import { serve, file } from "jstime";
serve({ fetch(req) { return new Response(JSTime.file("./hello.txt")); },});⚡️ Speed — JSTime automatically uses the sendfile(2) system call when possible, enabling zero-copy file transfers in the kernel—the fastest way to send files.
You can send part of a file using the slice(start, end) method on the JSTime.file object. This automatically sets the Content-Range and Content-Length headers on the Response object.
JSTime.serve({ fetch(req) { // parse `Range` header const [start = 0, end = Infinity] = req.headers .get("Range") // Range: bytes=0-100 .split("=") // ["Range: bytes", "0-100"] .at(-1) // "0-100" .split("-") // ["0", "100"] .map(Number); // [0, 100]
// return a slice of the file const bigFile = JSTime.file("./big-video.mp4"); return new Response(bigFile.slice(start, end)); },});Benchmarks
Section titled “Benchmarks”Below are JSTime and Node.js implementations of a simple HTTP server that responds JSTime! to each incoming Request.
JSTime.serve({ fetch(req: Request) { return new Response(`JSTime!`); }, port: 3000,});require("http") .createServer((req, res) => res.end("JSTime!")) .listen(8080);The JSTime.serve server can handle roughly 2.5x more requests per second than Node.js on Linux.
| Runtime | Requests per second | | --- | --- | | Node 16 | ~64,000 | | JSTime | ~160,000 |
Reference
Section titled “Reference”interface JSTime { serve(options: { fetch: (req: Request, server: Server) => Response | Promise; hostname?: string; port?: number; development?: boolean; error?: (error: Error) => Response | Promise; tls?: { key?: | string | TypedArray | BunFile | Array<string | TypedArray | BunFile>; cert?: | string | TypedArray | BunFile | Array<string | TypedArray | BunFile>; ca?: string | TypedArray | BunFile | Array<string | TypedArray | BunFile>; passphrase?: string; dhParamsFile?: string; }; maxRequestBodySize?: number; lowMemoryMode?: boolean; }): Server;}
interface Server { development: boolean; hostname: string; port: number; pendingRequests: number; stop(): void;}