Skip to main content

Deploying Bun Applications

This comprehensive guide covers everything you need to know about deploying Bun applications via Deploy with Git, from simple Elysia APIs to complex applications using Hono, or even Node.js-compatible frameworks running on Bun.

Overview​

Deploy with Git automatically detects Bun applications by looking for:

  • bun.lockb file (Bun's binary lockfile)
  • bunfig.toml (Bun configuration file)
  • .bun-version for version specification (optional)

Basic Bun Deployment​

Simple Elysia API​

docker run -d \
--name elysia-api \
-e GIT_REPO_URL=https://github.com/your-username/elysia-api \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest

What Happens Automatically​

  1. Detection: Finds bun.lockb or bunfig.toml and identifies as Bun project
  2. Version Selection:
    • Checks BUN_VERSION environment variable
    • Checks .bun-version file
    • Checks engines.bun in package.json
    • Falls back to latest Bun version
  3. Runtime Installation:
    • Downloads official Bun binary from bun.sh
    • Installs to /opt/flux-tools/bun
    • Sets up PATH environment variables
  4. Dependencies: Runs bun install
  5. Build: Runs bun run build if build script exists (optional - Bun runs TypeScript natively!)
  6. Start: Executes bun run start or detected entry point

Framework-Specific Guides​

Elysia Framework​

Elysia is a Bun-native web framework designed for ergonomics and performance. Deploy with Git automatically detects and optimizes Elysia applications:

docker run -d \
--name elysia-rest-api \
-e GIT_REPO_URL=https://github.com/your-username/elysia-api \
-e APP_PORT=3000 \
-e BUN_VERSION=1.0.25 \
-p 3000:3000 \
runonflux/orbit:latest

Example index.ts:

import { Elysia } from 'elysia';

const app = new Elysia();
const port = process.env.APP_PORT || 3000;

app.get('/health', () => ({
status: 'healthy',
runtime: 'bun',
framework: 'elysia'
}));

app.get('/', () => ({
message: 'Hello from Elysia!',
runtime: `Bun ${Bun.version}`
}));

app.listen(port, () => {
console.log(`🦊 Elysia is running on port ${port}`);
});

Key Features:

  • Native TypeScript support (no transpilation needed)
  • Type safety with end-to-end type inference
  • High performance with Bun's optimizations

Hono Framework​

Hono is an ultra-fast web framework that works great with Bun:

docker run -d \
--name hono-api \
-e GIT_REPO_URL=https://github.com/your-username/hono-api \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest

Example index.ts:

import { Hono } from 'hono';

const app = new Hono();
const port = Number(process.env.APP_PORT) || 3000;

app.get('/health', (c) => {
return c.json({ status: 'healthy', runtime: 'bun' });
});

app.get('/', (c) => {
return c.json({
message: 'Hello from Hono!',
runtime: `Bun ${Bun.version}`
});
});

export default {
port,
fetch: app.fetch,
};

console.log(`Hono is running on port ${port}`);

Express on Bun​

Bun is compatible with Node.js frameworks like Express:

docker run -d \
--name express-bun \
-e GIT_REPO_URL=https://github.com/your-username/express-app \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest

Example:

import express from 'express';

const app = express();
const port = process.env.APP_PORT || 3000;

app.get('/health', (req, res) => {
res.json({ status: 'healthy', runtime: 'bun' });
});

app.get('/', (req, res) => {
res.json({ message: 'Express running on Bun!' });
});

app.listen(port, () => {
console.log(`Express on Bun listening on port ${port}`);
});

Next.js on Bun​

Bun can run Next.js applications:

docker run -d \
--name nextjs-bun \
-e GIT_REPO_URL=https://github.com/your-username/nextjs-app \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest

Note: Ensure your package.json has a start script:

{
"scripts": {
"build": "next build",
"start": "next start"
}
}

Version Management​

Specify Bun Version​

Option 1: Environment Variable

docker run -d \
-e GIT_REPO_URL=https://github.com/your-username/bun-app \
-e APP_PORT=3000 \
-e BUN_VERSION=1.0.25 \
-p 3000:3000 \
runonflux/orbit:latest

Option 2: .bun-version File

1.0.25

Option 3: package.json Engines

{
"name": "my-bun-app",
"engines": {
"bun": ">=1.0.0"
}
}

Native TypeScript Execution​

One of Bun's killer features is native TypeScript execution - no build step required!

TypeScript Without Build​

docker run -d \
--name ts-api \
-e GIT_REPO_URL=https://github.com/your-username/typescript-api \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest

Your index.ts runs directly without transpilation:

interface ApiResponse {
message: string;
timestamp: Date;
}

const response: ApiResponse = {
message: 'TypeScript running natively!',
timestamp: new Date()
};

console.log(response);

When to Use Build Scripts​

Use a build script when you need:

  • Asset bundling for frontend applications
  • Code minification for production
  • Special build optimizations
{
"scripts": {
"build": "bun build ./src/index.ts --outdir ./dist --target bun",
"start": "bun run ./dist/index.js"
}
}

Environment Variables​

Bun-Specific Variables​

VariableDescriptionDefault
BUN_VERSIONBun version to installAuto-detected or latest

Common Application Variables​

docker run -d \
--name bun-api \
-e GIT_REPO_URL=https://github.com/your-username/bun-api \
-e APP_PORT=3000 \
-e BUN_VERSION=1.0.25 \
-e DATABASE_URL=postgres://user:pass@db:5432/mydb \
-e JWT_SECRET=your-secret-key \
-e LOG_LEVEL=info \
-p 3000:3000 \
runonflux/orbit:latest

Advanced Scenarios​

Monorepo - Deploy Specific Package​

docker run -d \
--name bun-auth-service \
-e GIT_REPO_URL=https://github.com/your-username/monorepo \
-e PROJECT_PATH=packages/auth \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest

Private Repository​

docker run -d \
--name private-bun-api \
-e GIT_REPO_URL=https://github.com/your-username/private-api \
-e GIT_TOKEN=ghp_your_personal_access_token \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest

With Deployment Hooks​

Create pre-deploy.sh in your repository root:

#!/bin/bash
# Check Bun runtime before deployment
echo "Checking Bun runtime..."
bun --version

# Run tests
echo "Running tests..."
bun test

Create post-deploy.sh:

#!/bin/bash
# Health check after deployment
echo "Performing health check..."
curl -f http://localhost:$APP_PORT/health || exit 1

echo "Deployment successful!"
docker run -d \
--name bun-api-with-hooks \
-e GIT_REPO_URL=https://github.com/your-username/bun-api \
-e APP_PORT=3000 \
-p 3000:3000 \
runonflux/orbit:latest

CI/CD Integration​

Automatic Deployment with Webhooks​

docker run -d \
--name bun-api \
-e GIT_REPO_URL=https://github.com/your-username/bun-api \
-e APP_PORT=3000 \
-e WEBHOOK_SECRET=my-secret-phrase \
-p 3000:3000 \
-p 9001:9001 \
runonflux/orbit:latest

Configure GitHub Webhook:

  • Payload URL: https://your-app-9001.app.runonflux.io/webhook
  • Content type: application/json
  • Secret: my-secret-phrase
  • Events: Just the push event

Polling for Updates​

docker run -d \
--name bun-api \
-e GIT_REPO_URL=https://github.com/your-username/bun-api \
-e APP_PORT=3000 \
-e POLLING_INTERVAL=300 \
-p 3000:3000 \
runonflux/orbit:latest

Troubleshooting​

Bun Not Detected​

Problem: Application detected as Node.js instead of Bun

Solution: Ensure you have bun.lockb in your repository:

# Generate bun.lockb
bun install
git add bun.lockb
git commit -m "Add bun.lockb for Bun detection"

Entry Point Not Found​

Problem: "No entry point found for Bun application"

Solution: Ensure you have either:

  1. A start script in package.json:
{
"scripts": {
"start": "bun run index.ts"
}
}
  1. Or a common entry point file: index.ts, index.js, src/index.ts, main.ts, server.ts, or app.ts

Port Binding Issues​

Problem: Application not accessible

Solution: Ensure your Bun application binds to 0.0.0.0 (not localhost):

// Good: Accessible from outside container
app.listen(port, '0.0.0.0', () => {
console.log(`Server running on port ${port}`);
});

// Also good (default in most frameworks)
app.listen(port);

TypeScript Type Errors​

Problem: TypeScript compilation errors even though Bun runs TS natively

Solution: Bun runs TypeScript without strict type checking. For development, fix type errors locally:

# Check types locally before pushing
bun run tsc --noEmit

Add to package.json:

{
"scripts": {
"typecheck": "tsc --noEmit",
"start": "bun run index.ts"
}
}

Dependencies Not Installing​

Problem: bun install fails

Solution: Check for bunfig.toml configuration issues or try clearing Bun cache:

# In pre-deploy.sh
bun pm cache rm
bun install

Performance Tips​

  1. Native TypeScript: Skip build steps when possible - Bun runs TypeScript natively
  2. Bun.serve API: For maximum performance, use Bun's native server API instead of Express
  3. Dependency Caching: Dependencies are cached based on bun.lockb hash
  4. Health Checks: Implement /health endpoint for faster deployment verification
  5. Hot Module Reloading: Use bun --hot in development (not needed in production)

Bun-Native APIs​

Bun provides high-performance native APIs:

Bun.serve (High Performance)​

const server = Bun.serve({
port: process.env.APP_PORT || 3000,
fetch(req) {
const url = new URL(req.url);

if (url.pathname === '/health') {
return new Response(JSON.stringify({ status: 'healthy' }), {
headers: { 'Content-Type': 'application/json' }
});
}

return new Response('Hello from Bun.serve!');
},
});

console.log(`Server running on port ${server.port}`);

File I/O with Bun.file​

// Fast file reading
const file = Bun.file('data.json');
const data = await file.json();

// Fast file writing
await Bun.write('output.json', JSON.stringify(data));

SQLite with Bun​

import { Database } from 'bun:sqlite';

const db = new Database('mydb.sqlite');
const query = db.query('SELECT * FROM users WHERE id = ?');
const user = query.get(1);

Example Repository Structure​

my-bun-api/
├── package.json # Dependencies and scripts
├── bun.lockb # Bun lockfile (binary format)
├── .bun-version # Optional: Pin Bun version
├── bunfig.toml # Optional: Bun configuration
├── tsconfig.json # TypeScript configuration
├── index.ts # Application entry point
├── pre-deploy.sh # Optional: Pre-deployment hook
├── post-deploy.sh # Optional: Post-deployment hook
├── src/
│ ├── routes/
│ │ ├── users.ts
│ │ └── auth.ts
│ ├── models/
│ │ └── user.ts
│ └── middleware/
│ └── auth.ts
└── test/
└── api.test.ts

Next Steps​