Runtime
Run TypeScript, execute scripts, read environment variables, and serve HTTP
Last updated on
When to use it
Use the Bun runtime when the goal is to execute JavaScript or TypeScript, rather than install dependencies, run tests, or emit a bundle.
bun run index.ts
bun index.ts # shorthand
bun run dev # package.json script
bun --watch index.ts # restart on file changes
bun --hot index.ts # hot reload with state preservation where possibleTypeScript and modules
Bun parses .ts, .tsx, JSX, and common ESM/CommonJS patterns. Execution strips types; static checking remains a TypeScript job:
bun add -d typescript
bunx tsc --noEmitEnvironment variables
Bun automatically reads common .env files. Use process.env or Bun.env, and validate required values at startup:
const port = Number(Bun.env.PORT ?? 3000);
const apiKey = Bun.env.API_KEY;
if (!apiKey) throw new Error('API_KEY is required');Never put server secrets into source, logs, untrusted agent context, or browser bundles.
HTTP server
const server = Bun.serve({
port: Number(Bun.env.PORT ?? 3000),
routes: {
'/health': () => Response.json({ ok: true }),
'/users/:id': (req) => Response.json({ id: req.params.id }),
},
fetch() {
return new Response('Not found', { status: 404 });
},
});
console.log(server.url.href);Common runtime APIs
| Goal | API | Boundary |
|---|---|---|
| Files | Bun.file() / Bun.write() | Bun.file() returns a lazy Blob-like value |
| HTTP | Bun.serve() | Uses standard Request and Response |
| Processes | Bun.spawn() / Bun.spawnSync() | Prefer argument arrays for untrusted input |
| Passwords | Bun.password | Do not substitute a general fast hash |
| SQLite | bun:sqlite | You still own migrations and resource lifetime |
| SQL | Bun.SQL | PostgreSQL, MySQL, and SQLite; budget pools and own migrations |
| Redis | RedisClient | Currently requires Redis 7.2+; close long-lived connections |
| Object storage | S3Client | S3-compatible services; provider policy still applies |
| Shell | Bun.$ | Keep command structure trusted; never interpolate unchecked input |
See Data and storage for database, cache, and object-storage boundaries.
Graceful shutdown
const server = Bun.serve({ fetch: () => new Response('ok') });
async function shutdown() {
await server.stop();
process.exit(0);
}
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);A production service should also drain databases and queues with a bounded timeout.
Cloud boundaries
Bun.servehonorsPORT, or you can setport; do not hard-code a port when the container platform injects one.- It listens on all interfaces by default. Use platform network policy, a reverse proxy, and application authentication to control access.
- The default idle timeout is 10 seconds. Evaluate
idleTimeoutfor AI streams or long requests and, when appropriate, useserver.timeout(request, 0)for a specific request while retaining application-level cancellation and total timeouts. - Set
maxRequestBodySize; do not buffer unbounded uploads in memory.
Official references: Runtime, HTTP server, and Bun APIs.