Bun deep dive: config, tests, workspaces

Beyond the basics — bunfig.toml settings, Bun's built-in test runner, and how monorepo workspaces behave on Falix, with the one-entry-per-server reality called out.

The Bun application gets you running fast: native TypeScript, auto bun install, bind SERVER_PORT. This guide goes a layer deeper into three features that come up once your project grows — Bun's config file, its built-in test runner, and workspaces — and is honest about how each meets the Falix one-entry-per-server model.

At a glance
You need A Falix server running the Bun application
Plan Any
Time Twenty minutes
Good to already know Bun on Falix (Main file, auto install, SERVER_PORT)

bunfig.toml: Bun's config file

bunfig.toml in your server root configures how Bun installs, tests, and runs. It's optional — Bun's defaults are sensible — but it's where you tune behaviour when you need to. A small, real example:

[install]
exact = true          # write exact versions, not ^ranges, to package.json

[test]
coverage = false      # or true to print coverage after `bun test`

Bun reads this automatically on any command; there's nothing to enable. Common things people set here are the install behaviour ([install]), a private registry, and test options ([test]). Keep it minimal — only add a key when a default isn't what you want. The full set of keys lives in the official docs.

🎯 Good to know: bunfig.toml is just configuration — it doesn't change what runs on start. The Bun app still runs bun install (when a package.json exists) and then bun run <Main file>. The config only shapes how those steps behave.

bun test: the built-in test runner

Bun ships a test runner — no jest, no vitest, nothing to install. It discovers files named *.test.ts, *.test.js, *.spec.ts (and the .js/.jsx/.tsx variants), and gives you a Jest-style API from bun:test:

// math.ts
export const add = (a: number, b: number) => a + b;
// math.test.ts
import { test, expect } from 'bun:test';
import { add } from './math';

test('add sums two numbers', () => {
  expect(add(2, 3)).toBe(5);
});

Run bun test and you get:

math.test.ts:
(pass) add sums two numbers

 1 pass
 0 fail

describe, beforeEach, mock, and the usual matchers are all there under bun:test.

Where do tests run on Falix, though? The Bun app's start command runs your app (bun run <Main file>), not your tests — you don't point the Main file at a test file. So run bun test where testing belongs:

  • Locally, before you deploy — the normal place.
  • As a build check via a Git post-deploy command: add bun test so a deploy that fails its tests is visible in the deploy log. (It won't block the server from starting, but you'll see the failure.)

Workspaces, honestly

Bun supports monorepo workspaces: a root package.json lists workspace folders, and packages depend on each other with workspace:*.

{
  "name": "monorepo",
  "private": true,
  "workspaces": ["packages/*", "apps/*"]
}
{
  "name": "@demo/api",
  "dependencies": { "@demo/lib": "workspace:*" }
}

On Falix this works: the Bun app runs bun install at your container root (where the root package.json is), which links the workspace packages together, and you can set the Main file to a workspace entry like apps/api/index.ts. When it runs, its import { thing } from '@demo/lib' resolves to your local package — no publishing, no copying.

⚠️ Heads up: A Falix server launches one entry file. A monorepo runs fine, but you're only starting one app from it — the Main file you chose. To run a genuinely separate app from the same repo (a second bot, another API), don't try to start two things in one server; give it its own Instance, an isolated app and startup on the same server.

Reinstalls and node_modules

As with Node, node_modules (and Bun's linked workspace symlinks) aren't yours to keep — a reinstall or an application switch wipes them. You don't rebuild by hand: bun install runs on the next start and restores everything from your package.json files and lockfile. Guard your source and data (managed databases are the home for data), not node_modules.

Troubleshooting

  • bun test finds no tests — your files aren't named *.test.ts/*.spec.ts, or they're outside where Bun looks. Rename them or pass a path: bun test ./tests.
  • A workspace import fails at runtime — the bun install at the root didn't run or didn't link. Confirm the root package.json has the workspaces array, restart so install re-runs, and check the dependency uses workspace:*.
  • bunfig.toml seems ignored — it must sit in the directory Bun runs from (your server root) and be valid TOML; a syntax error makes Bun fall back to defaults.
  • Server starts then stops — your entry ran and exited. A server or bot stays alive by keeping a listener open; a script that just runs is done. See My app won't start.

Everything else about Bun — the bundler, the shell, the full config reference — is covered at the official docs, bun.sh.


Next steps

Was this guide helpful?