ยท5 min read

Perry: Compiling TypeScript Directly to Machine Code

How Perry eliminates the Node.js runtime and delivers 2x faster performance with tiny binaries

The TypeScript Runtime Problem

TypeScript has become the language of choice for millions of developers. The type safety, excellent tooling, and familiar JavaScript syntax make it ideal for everything from web apps to server-side code. But there's a catch.

To run TypeScript, you need Node.js. And Node.js comes with baggage:

  • 80+ MB runtime: Every deployment includes the entire V8 JavaScript engine
  • Cold start overhead: Lambda functions and containers spend hundreds of milliseconds just starting Node.js
  • Memory consumption: V8's garbage collector and JIT compiler add significant memory overhead
  • Distribution complexity: You can't just ship a binary โ€“ users need Node.js installed

For many use cases, this overhead doesn't matter. But for CLI tools, serverless functions, edge computing, and embedded systems, every megabyte and millisecond counts.

What if you could compile TypeScript directly to machine code?

Introducing Perry

Perry is a native TypeScript compiler written in Rust. It compiles your TypeScript code directly to standalone executables โ€“ no Node.js, no V8, no runtime required.

The results are striking:

  • 2-5 MB binaries instead of 80 MB Node.js installations
  • ~1ms startup time instead of hundreds of milliseconds
  • 2.2x faster execution compared to Node.js
  • Single-file distribution โ€“ just ship the executable

Perry isn't just a toy or proof-of-concept. It supports real TypeScript features: generics, classes, async/await, closures, and more.

How Perry Works

Perry's architecture leverages battle-tested Rust components:

1. SWC for Parsing

Perry uses SWC (Speedy Web Compiler) to parse TypeScript. SWC is already widely adopted in tools like Next.js and Deno for its performance โ€“ it's 20x faster than Babel. Written in Rust, it provides a fast, accurate TypeScript parser that handles all the language's syntax.

2. HIR Transformation

The parsed Abstract Syntax Tree (AST) is transformed into a High-Level Intermediate Representation (HIR). This representation is optimized for the next stage: code generation. During this phase, Perry performs type analysis and optimization passes.

3. Cranelift Code Generation

Cranelift generates the final machine code. It's the same code generator used by Wasmtime and other WebAssembly runtimes. Cranelift produces efficient native code for x86-64, ARM64, and other architectures.

4. NaN-Boxing for Union Types

TypeScript's union types (like string | number) pose a challenge for native compilation. Perry uses NaN-boxing โ€“ a clever technique that encodes type information in the unused bits of 64-bit floats โ€“ to efficiently represent dynamic types at runtime.

Performance Benchmarks

The numbers speak for themselves:

| Metric | Node.js | Perry | Improvement | |--------|---------|-------|-------------| | Binary Size | ~80 MB | 2-5 MB | 16-40x smaller | | Cold Start | 200-500ms | ~1ms | 200-500x faster | | Execution | baseline | 2.2x faster | 2.2x |

For CLI tools that run once and exit, the startup time difference is transformative. A Node.js CLI might spend 300ms just starting before executing a single line of your code. A Perry-compiled CLI is already done.

TypeScript Feature Support

Perry supports the TypeScript features developers actually use:

  • Generics: Full generic type support
  • Classes: Inheritance, static members, access modifiers
  • Async/Await: Native async support without Promises overhead
  • Closures: First-class function support
  • Type Guards: Runtime type narrowing
  • Enums: Both string and numeric enums
  • Modules: ES module import/export

npm Ecosystem Compatibility

One of Perry's most impressive features is its native reimplementation of popular npm packages. Instead of running JavaScript through V8, these packages are reimplemented in Rust:

  • Database: PostgreSQL, MongoDB, MySQL, SQLite
  • Security: bcrypt, crypto, jwt
  • HTTP: fetch, http client/server
  • Utilities: Buffer, path, fs, os, child_process
  • Data: JSON, Math, Date, RegExp

27+ packages are currently supported, with more being added. This means your existing TypeScript code that uses these libraries can compile to native code without modification.

Use Cases

CLI Tools

Perry is ideal for command-line tools. Instead of requiring users to install Node.js, you ship a single executable. The instant startup time makes the tool feel native โ€“ because it is.

# Traditional Node.js CLI
npm install -g my-cli  # Requires Node.js
my-cli --help          # 200ms startup

# Perry-compiled CLI
./my-cli --help        # <1ms startup

Serverless Functions

Cold starts kill serverless performance. A Lambda function that takes 500ms to cold start is burning money and frustrating users. Perry-compiled functions start in milliseconds, making serverless viable for latency-sensitive workloads.

Edge Computing

Edge runtimes like Cloudflare Workers have strict size limits. Perry's 2-5 MB binaries fit where 80 MB Node.js installations never could. Deploy TypeScript to the edge without compromising on language features.

Embedded Systems

IoT devices and embedded systems often have limited resources. Perry brings TypeScript's developer experience to environments where Node.js was never an option.

Getting Started

Perry is open source under MIT and Apache 2.0 licenses. Visit perryts.com to:

  1. Download the compiler for your platform
  2. Read the documentation for language support details
  3. Explore examples of Perry-compiled applications
  4. Contribute to the project on GitHub

The Future of TypeScript

Perry represents a fundamental shift in what's possible with TypeScript. By eliminating the runtime, it opens TypeScript to use cases that were previously impractical โ€“ from embedded systems to high-frequency trading bots.

The project is actively developed and the ecosystem is growing. As more npm packages get native implementations and TypeScript feature coverage expands, Perry becomes increasingly viable for production use.

If you've ever wished TypeScript could compile to native code, Perry is making that dream a reality.


Perry is an open source project. Visit perryts.com to learn more.

Questions or feedback about this article? We'd love to hear from you.

typescriptcompilerrustperformanceopen-source
Perry: Compiling TypeScript Directly to Machine Code | Skelpo