Back to comparisons
TypeScript runtime

Perry vs Bun

Bun is an all-in-one JavaScript/TypeScript runtime, bundler, package manager, and test runner that can also produce single-file executables by bundling its runtime with your code. Perry takes a different path: it compiles TypeScript directly to native machine code via LLVM — no JavaScript engine in the binary, no runtime, just a small native executable. Bun and Perry overlap on the TS-to-binary output but disagree about whether a JavaScript engine should be in that binary.

What is Bun?

Bun is a fast, all-in-one JavaScript and TypeScript toolkit built in Zig. It runs `.ts` source directly (no precompile step), uses JavaScriptCore as its JS engine, and includes a bundler, package manager, and test runner. `bun build --compile` bundles the Bun runtime together with your application into a single executable. Bun targets Linux, macOS, and Windows on x64 and arm64.

What is Perry?

Perry is a native TypeScript compiler written in Rust. It compiles TypeScript directly to native machine code via LLVM — no JavaScript engine, no runtime, no JIT. The output is a single binary (around 330 KB for a hello world; ~48 MB for a full stdlib app like a Fastify server). Perry targets 10 platforms including macOS, iOS, iPadOS, Android, Linux, Windows, watchOS, tvOS, WebAssembly, and the Web.

Side by side

FeaturePerryBun
OutputNative machine code (LLVM)Your code + Bun runtime bundled in one binary
JavaScript engine in binaryNone by default; optional V8 with --enable-js-runtime (+~15 MB)JavaScriptCore, always
Hello-world binary size~330 KB~50–100 MB (includes Bun runtime)
JITNo (AOT compiled)Yes (JavaScriptCore JIT)
Mobile targets (iOS, Android)Yes — native UI via UIKit/JNINo
Watch / TV targetswatchOS, tvOS, Wear OSNo
Native UI widgets25+ via AppKit, UIKit, GTK4, Win32, JNINo (server/CLI focus)
npm ecosystemPure-TS/JS packages can compile natively; others via optional V8Full Node-compatible npm
StabilityPre-1.0 (alpha)Stable (1.x)
Built inRustZig

Where Perry wins

  • +Smaller binaries — a Perry hello world is ~330 KB; a Bun --compile hello world includes the Bun runtime and lands in the tens of megabytes.
  • +No JavaScript engine cost. Perry-compiled binaries don't carry an interpreter or JIT — your TypeScript is the executable.
  • +Mobile, watch, and TV. Perry compiles to iOS, iPadOS, Android, watchOS, tvOS, and WebAssembly. Bun is server/desktop only.
  • +Native UI. Perry's perry/ui module compiles to real platform widgets (AppKit on macOS, UIKit on iOS, GTK4 on Linux, Win32 on Windows, JNI on Android). Bun has no UI story.
  • +Faster on most compute microbenches measured under matched conditions on M1 Max (RUNS=11, v0.5.279, 2026-04-25): fibonacci 318 ms vs Bun 589 ms; object_create 1 ms vs 6 ms; nested_loops 18 ms vs 21 ms. See perry/benchmarks for the full table.
  • +Faster on JSON validate-and-roundtrip in the dynamic-typing pack: Perry's lazy JSON tape lands at 75 ms median vs Bun's 259 ms on the same 10k-record workload.

Where Bun wins

  • +Mature, stable runtime with 1.x releases. Perry is pre-1.0.
  • +Faster on JSON parse-and-iterate (where every value is touched): Bun 254 ms vs Perry 466 ms median on the same workload — Perry's lazy tape can't shortcut when iteration is forced.
  • +Full Node-compatible npm ecosystem out of the box. Perry runs a subset natively and falls back to optional embedded V8 for the rest.
  • +Built-in test runner, bundler, and package manager. Perry is a compiler — adjacent tooling is separate.
  • +JIT-warm performance can outpace AOT on iteration-heavy code with hot inner loops; Perry has no JIT.
  • +Tied with Perry to within run-to-run noise on `loop_data_dependent` (232 ms vs 235 ms) — the genuinely-non-foldable f64 kernel where neither side's compiler can reorder. Source: perry/benchmarks RUNS=11.

When to choose Perry

Choose Perry when binary size matters (mobile distribution, embedded contexts, fast cold starts), when you want to ship to mobile/watch/TV from one TypeScript codebase, when you want native UI widgets, or when you don't want a JavaScript engine in your shipped artifact at all.

When to choose Bun

Choose Bun when you need a stable, mature runtime today, when full npm compatibility is non-negotiable, when you want a single tool for runtime + bundler + package manager + test runner, or when JIT-warm performance on long-running workloads matters more to you than cold-start size.

Verdict

Bun and Perry both let you ship a TypeScript program as a single binary, but they answer different questions. Bun's binary contains the Bun runtime and is optimized for backend/CLI workloads where JIT and full Node compatibility win. Perry's binary contains no JS engine and is optimized for size, cold-start, mobile, and native UI. If you're shipping a server, Bun is more proven today. If you're shipping a native app or care about binary size, Perry is built for that case.

Try Perry

Compile your TypeScript to native today.

Get started