Skip to content

Deploy with Bun

Bun provides ultra-fast startup and execution. Deploy your Stoma gateway with Bun for maximum performance.

  1. Install dependencies

    Terminal window
    bun install hono @homegrower-club/stoma
  2. Create your gateway

    For a minimal example, see the Basic Gateway partial. Here’s a typical production setup with the Bun adapter:

    src/index.ts
    import {
    createGateway,
    cors,
    requestLog,
    rateLimit,
    } from "@homegrower-club/stoma";
    import { bunAdapter } from "@homegrower-club/stoma/adapters/bun";
    const gateway = createGateway(
    {
    name: "my-gateway",
    basePath: "/api",
    policies: [requestLog(), cors()],
    routes: [
    {
    path: "/users/*",
    pipeline: {
    policies: [rateLimit({ max: 100, window: 60 })],
    upstream: {
    type: "url",
    target: "https://api.example.com",
    rewritePath: (path) => path.replace("/api", ""),
    },
    },
    },
    ],
    },
    // Production adapter with rate limiting and caching support
    bunAdapter()
    );
    export default gateway.app;
  3. Create the server entry

    src/server.ts
    import gateway from "./index";
    Bun.serve({
    fetch: gateway.fetch,
    port: parseInt(process.env.PORT || "3000"),
    });
    console.log("Gateway running on http://localhost:3000");
  4. Run

    Terminal window
    bun run src/server.ts

Use the Bun adapter for production deployments:

src/index.ts
import {
createGateway,
cors,
rateLimit,
cache,
} from "@homegrower-club/stoma";
import { bunAdapter } from "@homegrower-club/stoma/adapters/bun";
const adapter = bunAdapter();
const gateway = createGateway({
name: "my-gateway",
basePath: "/api",
adapter,
policies: [cors()],
routes: [
{
path: "/users/*",
pipeline: {
policies: [
rateLimit({
max: 100,
windowSeconds: 60,
store: adapter.rateLimitStore,
}),
],
upstream: {
type: "url",
target: "https://api.example.com",
},
},
},
],
});
export default gateway.app;
src/server.ts
import gateway from "./index";
const server = Bun.serve({
fetch: gateway.fetch,
port: 3000,
});
console.log(`Listening on http://localhost:${server.port}`);
src/server.ts
import gateway from "./index";
const server = Bun.serve({
fetch: gateway.fetch,
port: 443,
tls: {
cert: Bun.file("./cert.pem"),
key: Bun.file("./key.pem"),
},
});

For reverse proxy integration (nginx, Caddy):

src/server.ts
import gateway from "./index";
Bun.serve({
fetch: gateway.fetch,
unix: "/tmp/gateway.sock",
});
railway.toml
[build]
builder = "bun"
[deploy]
startCommand = "bun run src/server.ts"

Or use package.json:

{
"scripts": {
"start": "bun run src/server.ts"
}
}
render.yaml
services:
- type: runtime
runtime: bun
buildCommand: bun install
startCommand: bun run src/server.ts
envVars:
- key: NODE_ENV
value: production
fly.toml
app = "stoma-gateway"
[build]
builder = "ghcr.io/oven-sh/bun-docker"
[[vm]]
cpuKind = "shared"
cpus = 1
memoryMB = 256

If using Deno Deploy, you can run Bun-compiled code or use Deno:

src/server.ts
import gateway from "./index";
Deno.serve(gateway.app.fetch);
  • Use Bun’s built-in HTTP server (not Node.js compatibility mode)
  • Leverage Bun’s native TypeScript support - no transpilation needed
  • Use --bun flag when running TypeScript directly:
Terminal window
bun --bun src/index.ts
src/index.ts
const gateway = createGateway({
name: process.env.GATEWAY_NAME || "my-gateway",
basePath: process.env.BASE_PATH || "/api",
debug: process.env.DEBUG === "true",
});
.env
GATEWAY_NAME=my-gateway
PORT=3000
DEBUG=false
RuntimeCold StartRequest/Second
Node.js~200ms~10k
Bun~30ms~50k
Cloudflare Workers~5ms~15k