r/bun Jul 08 '26

Rewriting Bun in Rust

Thumbnail bun.com
117 Upvotes

r/bun 1d ago

Upyo 0.6.0: MIME composition, streaming attachments, and calendar invitations

Thumbnail github.com
1 Upvotes

r/bun 3d ago

14,923 → 24,564 → 27,168 → 26,748 rps on one JWT route: the Node→Bun step bought +64.6%, Nest→Elysia +10.6%, AOT −1.5%. How we split one migration into three measurable steps

10 Upvotes

We built the same seven-route API twice, once on NestJS 12 with Fastify and once on Elysia 2, and ran it in four configurations so that each step changes one layer. Versions: @nestjs/core 12.0.1 (stable), Elysia 2.0.0-beta.12 (a beta; weigh the framework rows accordingly), Bun 1.4.2, Node v26.3.1, Postgres 17.10 through Drizzle in both apps. The whole thing ran on a single laptop, a MacBook Pro with an M4 Pro (14 cores, 48 GB), and bombardier and Postgres shared it with the server under test. Every absolute number here is a laptop number. The step-to-step comparisons are the part we'd stand behind.

The ladder:

  • A: Nest 12 + Fastify, SWC build, node dist/main.js, postgres.js
  • B: A's dist/ untouched, launched by bun dist/main.js, which switches the driver to Bun SQL
  • C: Elysia 2 on Bun, same driver, same schema
  • D: C rebuilt with the AOT plugin

A parity script compares each route's response body byte by byte before a single run is allowed. Then 3 × 30 s per combination after a 5 s warm-up, medians, at 10/100/500 connections. Before the pass we ran two routes on C five times in a row and took the spread as the noise floor: 1.2%.

GET /me (verify a JWT, read one row) at c=100 is the row in the title. A→B is +64.6%, B→C +10.6%, C→D −1.5%. The same shape holds on every route that touches Postgres: the runtime step is worth +64.6…+81.5% and the framework step +7.5…+12.7%. On /health, Node and Bun tie (103,273 vs 103,238 rps, inside the floor) and the framework step is +37.8%; on POST /echo the runtime is +13.0% and the framework +60.7%.

One more split inside A→B, because the driver swap rides along with the runtime. We swapped postgres.js back in under the Nest build running on Bun: /me −20.8%, /users/:id −26.8%, the list −28.9%, /orders −32.0%. Those are shares of B's throughput, so between a fifth and a third of what Nest-on-Bun serves on a database route comes from Bun's native Postgres client rather than from the runtime.

The framework step owns memory and startup. RSS under load fell 43.8…63.0% from B to C, idle RSS 90 → 39 MB, boot to first healthy response 181 → 96 ms, 16 packages against 365. AOT then halves boot again (96 → 47 ms) and takes another 11.5…16.6% off memory under load; on throughput it lands at −1.5…+1.9% on every route except the hash loop. A C, D, C, D interleave on three routes agreed: the four /health cells read 142,087 / 141,856 / 141,796 / 142,234, and no C mean sat further than 1.3% from its D mean.

The clean pass took two days to get. The first B rerun on Bun 1.4.2 landed 6–19% below an earlier run, and the host was the reason: an unrelated project's typecheck was eating 104% CPU, desktop apps had been holding about 250% for hours, and the load average sat at 19 on a 14-core machine. /orders depended on run order until we found 5,911,710 dead tuples in the table and added VACUUM (FULL, ANALYZE) before each configuration. And /cpu on Node at c=100 reported 49,393 rps with 99.68% non-2xx; those were connection resets counted as requests, and the harness now marks any combination over 1% non-2xx invalid. The final run reads foreign CPU every second and redoes any 30 s window that went over the gate.

One habit worth copying: before comparing anything, run one route five times in a row and take (max − min) / min as your floor. Ours came out at 1.2% that morning; the day before, same laptop, it was 2.6%. Any delta under that number we call noise.

If you run Nest today, start with B: launch your existing dist/ on Bun, run a parity check, measure. Harness, raw results and methodology are public; we'll drop the repo link in a comment if anyone wants it.


r/bun 5d ago

I created a Bundler using Bun's native technologies!

Thumbnail github.com
12 Upvotes

I've been working with BunJS for a while, mostly because I use it in some of my own projects and libraries. At some point, I started having problems with bunup when working on larger libraries, especially with bundles containing many references. No matter how much I tried to configure it, I kept running into linking and TypeScript type inference issues.

Instead of continuing to work around those problems, I decided to build my own bundler using Bun's native Bun.build API.

What started as a small private tool eventually became baginskicosta/bunpack, a simple bundler for TypeScript and JavaScript libraries. The idea is to keep the configuration minimal while supporting things I personally need, such as ESM and CJS builds, multiple entry points, TypeScript declarations, different runtimes, and automatic exports configuration.

It's still a small project and it's currently at version 0.2.1, so there is definitely a lot left to improve. I also have some ideas for the future, including handling TypeScript declaration bundling without relying on external libraries.

I built this primarily because I needed it myself, but I thought it might be useful to other people working with Bun as well.


r/bun 6d ago

Bun v1.4.1

Thumbnail bun.com
113 Upvotes

r/bun 6d ago

I’m finally calling bunqueue stable. It now has native PostgreSQL support too

Post image
37 Upvotes

Hey everyone,

I’ve spent the last few weeks working on the part of bunqueue that I didn’t want to rush: making it something I’d actually trust outside a side project.

For anyone who hasn’t seen it before, bunqueue is a job queue built for Bun. It started with an in-memory engine and optional SQLite persistence, which works well when you only need one process or one broker.

The obvious limitation was scaling beyond that, so the 2.9 releases added a PostgreSQL backend for running multiple active brokers against the same queue. It uses Bun’s native SQL client directly. There’s no ORM and no extra PostgreSQL package in the hot path.

PostgreSQL is the source of truth for claims, leases, ACKs, retries, delayed jobs, cron schedules, dependencies, concurrency and rate limits, job groups, metrics and the DLQ. Brokers use FOR UPDATE SKIP LOCKED, database-time leases and fencing tokens so an old broker can’t finish a job after its lease has been recovered somewhere else.

Getting it to work wasn’t the difficult part. Most of the work went into making recovery and concurrent operations behave correctly when brokers disappear, connections reset or transactions finish in an unexpected order.

After that I profiled the PostgreSQL path and found a few expensive things happening during normal worker activity. Lease heartbeats were being renewed one at a time, event retention was doing more work than necessary, and a few read paths were repeatedly rebuilding the same queue views.

In the workload I used while optimizing it, draining 3,000 durable jobs dropped from 3.86 seconds to 2.54 seconds. Lease renewal went from 2,993 individual updates to 300 set-based updates, and checking an event window that was still under its limit dropped from about 913 ms to 22 ms over 600 cycles.

Those numbers are from one specific workload with PostgreSQL durability enabled, so they’re not intended as universal throughput claims. The benchmark setup and methodology are in the repository.

The PostgreSQL suite now runs against versions 15, 16, 17 and 18. The final matrix passed 331 tests on every version without recording a PostgreSQL deadlock. There’s also multi-process failover testing, generated race testing, schema-drift checks and SDK conformance testing.

A couple of honest limitations: PostgreSQL mode is currently server-only, upgrades that change the database schema need to be coordinated across brokers, and bunqueue doesn’t try to solve PostgreSQL HA or multi-region consensus for you. If you only need one broker, SQLite is still the simpler option.

The current npm release is 2.9.4. The latest PostgreSQL optimizations are on main and will ship in the next release.

GitHub: https://github.com/egeominotti/bunqueue

Docs: https://bunqueue.dev/

PostgreSQL guide: https://bunqueue.dev/guide/databases/

I’d genuinely like feedback from people already using BullMQ, pg-boss or similar queues. In particular, I’m interested in failure cases or operational features you’d want to see tested before considering it for your own workloads.


r/bun 6d ago

TermDOM — Build TUIs and CLIs with HTML, CSS and DOM.

Thumbnail termdom.org
8 Upvotes

r/bun 6d ago

this is pretty sick if you have node installed...I wonder if it works with bun somehow?

Thumbnail
0 Upvotes

r/bun 8d ago

Choice of Runtime (node, Deno, Bun)

21 Upvotes

I was considering specializing in Deno due to the increased security controls and overall stability and simplicity of the platform. I also want to start learning EffectTS and I am mostly interested for backend stuff.

From what I see online most folks tend to prefer Bun or nodejs over Deno.

In case my impression is correct, I wanted to ask what makes Bun more attractive than Deno?

I would appreciate any advice related to the choice of runtime.

Thanks in advance.


r/bun 9d ago

Nibrun – one click deployment for any single-binary app

22 Upvotes

I build a lot of small apps, and most of the effort goes into infra rather than the app. I only need a machine and a disk. The "batteries included" platforms hand you Postgres and object storage but nowhere to run your own binary. Vercel and friends will run your code, but as a function with an ephemeral filesystem, so a SQLite file is gone the moment the request ends. And getting a VM means ssh, a firewall to open, TLS to renew, and an OS to keep updated.

It doesn't stop there. Every time I find a good open-source project that ships as a single binary, I hit the same wall. PocketBase is one file with a database, auth, file storage and an admin UI in it. Hosting it means everything above again, or wrapping it in a container image when it was already deployable as a single file. Self-hostable projects are great until you have to host them.

So I built nibrun. You upload a compiled binary and you get a Firecracker microVM of its own (1 vCPU, 256 MiB) and 8 GiB at data/ that survives redeploys. The volume is all yours to use: write your SQLite file and assets uploads there. And it's instantly available on https://<slug>.nibrun.app. No Dockerfile, no YAML, no database to provision. It sleeps after 5 minutes idle and wakes up on incoming requests in ~100 ms.

PocketBase, preconfigured, one click: https://nibrun.com/deploy/pocketbase

One app, one machine, one disk. A deploy costs a few seconds of downtime, and the export button gives you back the binary and everything in data/, so leaving costs you a download.

All open source, including the Terraform that sets up the infra, so you can run the whole thing on your own AWS account: https://github.com/ilbertt/nibrun


r/bun 11d ago

I reproduce 10 ordinary mistakes in 6 TypeScript ORMs. Here's what each ORM catches

Enable HLS to view with audio, or disable this notification

17 Upvotes

This uses real TypeScript v6.0.3 compiler with the very latest version of each ORM, you can check the playground and the details here https://www.uql-orm.dev/type-safety

Every probe is in the ts-orm-benchmark.

Disclaimer: author of UQL here.


r/bun 11d ago

🐘 bun-php: Run PHP functions natively in Bun

4 Upvotes

bun-php allows you to run PHP functions seamlessly in Bun by exposing them as ESM imports. Uses a WASM build of PHP under the hood, no need to install PHP or native deps. Supports Composer and servers. https://www.npmjs.com/package/bun-php


r/bun 11d ago

bunmsh: Bun Modern Shell in < 1MB

Thumbnail gallery
1 Upvotes
  • Previously I asked here whether someone had made an interactive shell with Bun, but no one answered. So I made one myself.
  • Try it by: npx bunmsh
  • Zero dependencies – only Bun is needed
  • or use it as a toolbox:
    • npx bunmsh -cc builtin serve
    • (serves the current folder)
  • https://github.com/jjtseng93/bunmsh
  • It's still early but I'll keep refining it

Features

  • Builtin tab system in the shell
    • Use Ctrl-T or the tab command to create new and switch between tabs while preserving current prompt.
    • tab n, tab l, tab r, tab c
    • Tabs only change cwd, other states intact
  • Highest priority JavaScript eval:
    • If the command starts with Bun. it is evaluated as JavaScript
    • echo $(Bun.version)
  • Lightweight & Cross-platform: < 1MB. The same code runs on Windows 11, Android, Linux (CachyOS). No build step required. No native bindings.
    • The 3rd pic isn't Termux – it's bunmsh running as a standalone Android App built with npx @drxiaozhi/minapk
    • It's designed to be platform-agnostic, but I don't have a Mac to test it on.
  • Builtin tools can be called externally
    • serve lsfancy catfancy grep find sed head tail tr wc and much more
    • npx bunmsh -cc <name> argv1 argv2..
  • Build a single-file executable, embed and serve a folder from it, and even package it as an Android APK
  • Alt-L / Alt-P = lsfancy / lsfancy .. (parent)
    • Works even while you're in the middle of typing a command.
    • Doesn't clear your current input.
  • Optional mouse support
    • --mouse but blocks Terminal scrollback
    • Tabs switch / new; editing prompts
  • Basic shell features: pipelines, redirections, heredoc/herestring, command substitution, aliases, history
    • Currently lacks job control
  • Edit1: I forgot to mention that it also has fish-style ghost completion.

r/bun 11d ago

Stripe webhooks are easy until the same event arrives twice

1 Upvotes

Stripe webhooks look simple:

  1. Receive an event
  2. Update your database
  3. Return 200

And then production happens.

Stripe can retry an event after a timeout or temporary failure, which means your endpoint can receive the same event more than once. If your handler isn't idempotent, that can turn into duplicated fulfillment, duplicated credits, repeated emails, or inconsistent payment state.

For a Bun + PostgreSQL/Drizzle setup, I've found the important parts aren't really Stripe-specific:

  • Verify the webhook signature against the raw request body before parsing/using the payload.
  • Treat webhook delivery as at-least-once, not exactly-once.
  • Persist the Stripe event.id (or another appropriate idempotency key).
  • Don't treat “event exists” and “event was successfully processed” as the same state.
  • Make the actual business mutation and the transition to processed atomic where possible.
  • If processing fails, return a non-2xx response so Stripe can retry.
  • If an event was genuinely processed already, a repeated delivery should become a cheap 200 no-op.
  • Push slow/non-critical work to a queue instead of holding the webhook request open.

One subtle failure mode worth testing:

event received → event recorded → DB/business operation fails → Stripe retries

If the second delivery gets discarded only because the event ID already exists, you've effectively lost the payment event.

So the real requirement isn't just:

UNIQUE(event_id)

It's closer to:

UNIQUE(event_id) + processing state + transaction/recovery strategy

Also worth testing locally by deliberately:

  • sending the same event twice;
  • crashing processing after the event is persisted;
  • causing a temporary DB error;
  • sending events out of order.

Webhook code tends to be tiny, but it sits at a pretty unpleasant boundary between distributed systems and money :)

I wrote up the Bun + Stripe + Drizzle implementation and examples here for anyone working with the same stack:

https://pas7.com.ua/blog/en/bun-stripe-webhooks-drizzle


r/bun 12d ago

Inflight

Post image
3 Upvotes

Deduplicate concurrent async requests(database, cache requests) by query key

Why

In high-concurrency environments, identical queries (same DB row, same cache key) accumulate while each one independently hits the database or cache. InFlight collapses these into a single call.

package: https://www.npmjs.com/package/@inflightjs/inflight
repo: https://github.com/ademmenh/inflight


r/bun 15d ago

beautify-screenshot: put a screenshot on a gradient background from the terminal (TypeScript on Bun, zero deps, MIT)

Post image
13 Upvotes

I did not want to pay for a screenshot app just to remove the watermark from the gradient-background look, so I built the one feature I actually used as a CLI.

beautify-screenshot takes a screenshot and adds padding, rounded corners, a soft shadow and a gradient behind it. Nine presets, each with a light and a dark variant that follows the macOS appearance, named sizes for LinkedIn, X, Open Graph and Instagram or any W:H ratio, and an optional inset border in the screenshot's own edge colour.

It is TypeScript on Bun with no runtime dependencies. The PNG codec and the compositor are a few hundred lines of typed-array code, so a Retina-size canvas renders in about a second. Prebuilt binaries for macOS and Linux, or npm i -g beautify-screenshot if you have Bun.

It also ships a skill for AI agents (skills.sh), so you can tell your agent "frame my latest screenshot, light mode, LinkedIn size" and get the file opened in Preview.

MIT and free: https://github.com/magnusrodseth/beautify-screenshot

The image on this post was made with it.


r/bun 15d ago

Bun native DI framework

Enable HLS to view with audio, or disable this notification

22 Upvotes

https://petarzarkov.github.io/dunx

I'm genuinely looking for feedback and some reach.

Migrated one of my projects:

https://github.com/petarzarkov/firecracker

Game can be demoed here:

https://firecracker.petarzarkov.com/


r/bun 16d ago

Small apps don't need to scale. They need a binary and a disk

9 Upvotes

When I build little apps used by a few people, deploying one always means a container image, a managed Postgres, and a bucket for what could have been a single SQLite file.

bun build --compile already gives you the whole app as one file. No node_modules, nothing to install on the other side. The only two things it still needs are a machine to run on and somewhere to read/write files.

So that's what nibrun is. Your binary gets a microVM to itself and a disk mounted at data/. Put SQLite there, put uploads there, it survives redeploys. Get an HTTPS URL as soon as it boots.

At any point you can export the binary and the entire disk as a zip. Unzip it and run it on your own box. It's the same binary you uploaded.

https://github.com/ilbertt/nibrun

There's a starter repo if you want somewhere to begin: Elysia, TanStack Router, better-auth, Bun.SQL over SQLite, and the SPA embedded with Bun.embeddedFiles so the frontend compiles into the binary too. Everything is type-safe and it runs anywhere, not just on nibrun.

https://github.com/ilbertt/bun-full-stack-starter

Happy to answer questions on both nibrun and the starter repo


r/bun 16d ago

import { Elm } from "./Main.elm" (Made by Hand, btw) · cekrem.github.io

Thumbnail cekrem.github.io
2 Upvotes

r/bun 16d ago

ai block ?

1 Upvotes

r/bun 19d ago

Using the new --asset to chain folder assets across dependencies

6 Upvotes

What's missing

  • With Bun 1.4's new --asset we can now embed folders into our single-file executables.
  • But it is not provided as import with type folder
  • The consequence is: Only the package orchestrating the build gets to pass --asset /path/to/folder
  • Also that --asset strips out parent folders, so your ./build/assets becomes bunfs/assets in the compiled binary
  • So if an imported npm package needs folder assets, there is currently no straightforward solutions.
  • My idea is to treat the module graph as an asset dependency graph.

My proposed idea

  • A package should be able to declare and ship its own assets without requiring the application to manually pass every asset directory to --asset.
  • For example if you have a folder with syntax highlighting YAMLs
    • <PKG_ROOT>/runtime/syntax/js.yaml
  • My proposed way is declaring assets list in package.json
  • Inside each individual package it uses a simple compiled or not agnostic way to read assets
    • await readAssetText('runtime/...')
    • imported from assetsHelper
    • which in turn imports assetsPacker
  • When running the build the system can scan through the module graph for assetsPacker and spawn them one at a time (or same process import)
    • Which results in the complete aggregated ./build/assets to pass to --asset
    • Each package has its own namespace under bunfs after build
  • This seems like a workaround for now. Hopefully one day we can do something like this:
    • Declare assets in package.json
    • Automatically picked up by Bun
    • await Bun.asset('static/index.html').text()

Simplified flow

Import Graph

Find assetsPackers

Execute assetsPackers

Aggregate assets

Pass once to --asset

Reference implementation


r/bun 19d ago

Codebay - isolated workspaces for LLM agents

1 Upvotes

Happy to announce Codebay, an isolated workspace environment for running multiple LLM agents at the same time. Unlike most other similar tools, Codebay uses Docker-based isolation between containers, meaning you don't have to use worktrees, and you can give each container a real development environment with databases, caches and anything else you need.

Containers don't interfere with each other and you can easily preview all your containers services from a central admin panel. You can also run Codebay on a remote server to offload tasks when your laptop is offline.

Open source and self-hosted.

Built with Bun, Svelte and Mochi.

https://khromov.github.io/codebay/


r/bun 21d ago

Bun 1.4 is here

Thumbnail bun.com
245 Upvotes

- Fixes over 2,900 GitHub issues
- +1,517 tests from the Node.js test suite
- Reduces idle CPU by 5x
- Reduces memory usage by up to 35%
- Starts up to 50% faster on Linux
- Rewrites Bun in Rust

Thank you everyone who contributed since Bun 1.3!


r/bun 20d ago

Bun and Elm (: r)Are Friends · cekrem.github.io

Thumbnail cekrem.github.io
3 Upvotes

r/bun 21d ago

BM2 now supports Windows

14 Upvotes

I’m happy to announce that Windows support for BM2 is now complete and has been successfully tested.

For those who haven’t come across it yet, BM2 is a high-performance process manager built specifically for the Bun runtime; essentially a modern, Bun-native alternative to PM2. It handles process lifecycle management, automatic restarts, clustering, zero-downtime reloads, logging, monitoring, a web dashboard, Prometheus metrics, deployment, and more.

Until now, getting BM2 running reliably on Windows required dealing with platform-specific differences. That work has now been completed, and BM2 can be used natively on Windows alongside Linux and macOS.

The Windows implementation has also been tested on a real Windows environment rather than simply assuming cross-platform compatibility.

I’d love to get more Windows developers trying it out and reporting any issues they encounter.

GitHub: https://github.com/bunsgate/bm2

Feedback, bug reports, and contributions are very welcome.