Bun 1.2 ships an HTTP server, built-in SQLite, and a Jest-compatible test runner in a single binary. See how it outperforms Node.js. Full breakdown.
What ships in one binary
Bun 1.2 packages three pieces teams usually stitch together from separate tools: an HTTP server, built-in SQLite, and a Jest-compatible test runner. You install one runtime and get request handling, local persistence, and a familiar test API without bolting on extra packages for the common path. That matters less as a marketing checklist and more as fewer moving parts when you scaffold a service, run tests in CI, and keep a small data store next to the app.
The practical upside is a shorter path from empty folder to working API. You still decide how to structure routes, schemas, and fixtures—but you spend less time choosing, installing, and aligning versions of server frameworks, database drivers, and test harnesses before the first real endpoint exists.
HTTP server: enough surface for real services
A built-in HTTP server is useful when the goal is a clear request pipeline rather than a full application framework. You define how requests are matched, how bodies are read, and how responses are written, then grow middleware-style helpers only where you need them. For many internal tools, webhooks, and small public APIs, that is enough: keep routing explicit, return proper status codes, and leave heavy concerns like auth, validation, and observability as deliberate layers instead of framework defaults you never inspect.
Compared with a Node.js stack that often starts with Express or Fastify plus adapters, the Bun path can feel thinner at the start. The tradeoff is the same one you face with any batteries-included runtime: if you later need ecosystem packages that assume Node’s module layout or HTTP primitives, plan for compatibility checks early rather than after the service is already live.
Built-in SQLite for local and single-node data
SQLite inside the runtime is a strong fit for single-node apps, local-first tools, caches, queues on disk, and prototypes that should not depend on a remote database from day one. You get durable storage with familiar SQL, zero network hop for reads and writes, and a simple backup story—copy a file. That is often the right default for CLI-adjacent services, developer tools, and early product iterations where operational simplicity beats horizontal scale.
It is the wrong default when you already need multi-writer concurrency across machines, managed failover, or a data model owned by a shared cluster. In those cases, treat built-in SQLite as a local side store or development stand-in, not the long-term system of record. Design migrations and query boundaries so swapping or dual-writing to a network database later does not rewrite the whole app.
- Use SQLite for config, sessions, job state, and feature-local tables that stay on one host.
- Keep hot paths free of unbounded full-table scans; index the columns you filter and join on.
- Separate “app data” from “ephemeral cache” so you know what must survive deploys.
Jest-compatible tests and the Node.js comparison
A Jest-compatible test runner lowers friction for teams already writing describe/it/expect style suites. You can often port unit and integration tests with small adjustments instead of rewriting assertions and mock patterns from scratch. Pair that with the same binary that serves HTTP and talks to SQLite, and end-to-end checks can run against real server and database code paths without a long list of test-only dependencies.
Bun is frequently positioned as outperforming Node.js on common workloads. Treat that as a prompt to measure your own critical paths—boot time, request latency under realistic payloads, test suite duration—not as a blanket reason to rewrite everything. Keep Node.js in the evaluation when libraries, hosting constraints, or team expertise still center there. Adopt Bun where the single-binary server, SQLite, and test runner actually shrink your stack and where your benchmarks on real traffic and CI confirm the win.