# Elide for Bun users

> Switching from Bun to Elide: what runs unchanged, which commands and APIs differ, benchmarks, strengths, weaknesses and the security model.

Elide runs the TypeScript, `node:*` modules and npm packages a Bun program uses; the `Bun` global is absent.

## Run the same code

```bash
elide app.ts                    # or: elide run app.ts
elide install --ecosystems=npm  # dependencies from package.json
elide test                      # node:test files
```

- TypeScript runs with no compile step and no `tsconfig.json`.
- Built-ins load with or without the `node:` prefix.
- A module that default-exports `{ fetch }` serves when run, as in Bun.

See [JavaScript and TypeScript](https://elide.help/docs/web), module status in the [API Overview](https://elide.help/docs/api-overview), and suite results
in the [Compatibility Matrix](https://elide.help/docs/compatibility).

## What changes

| Bun | Elide |
| --- | --- |
| `bun app.ts` | `elide app.ts` |
| `bun install` | `elide install --ecosystems=npm`; plain `elide install` skips npm |
| `bun.lock` | `aube-lock.yaml` |
| `bun run build` | `elide run build` |
| `bunx tool` | `elide run tool` for a tool in `node_modules/.bin`; no download-and-run |
| `bun test` with `expect` | `elide test` with `node:test` and `node:assert`; `expect` is unavailable |
| `bun --inspect app.ts` | `elide run --debugger=cdp app.ts` |
| `bun --watch`, `bun --hot` | No equivalent |
| `.env` loaded automatically | Call `process.loadEnvFile()` in code |
| `Bun.serve({ fetch })` | `Elide.serve({ fetch })` |
| `bun:sqlite` | `elide:sqlite`; see [SQLite](https://elide.help/docs/api-sqlite) |
| `Bun.file`, `Bun.write`, `Bun.$` | `node:fs` and `node:child_process` |
| Web `Worker` | `node:worker_threads` |
| `bun build`, `bun build --compile` | No equivalent |

## Benchmarks

Hello-world startup with `hyperfine -N -w 10 -r 100` on a 24-core AMD Ryzen Threadripper PRO 9965WX Linux workstation:

| Runtime | Command | Mean |
| --- | --- | --- |
| Bun | `bun hello.js` | 1.63 ± 0.18 ms |
| Elide | `elide run hello.js` | 1.43 ± 0.06 ms |
| Node | `node hello.js` | 11.70 ± 0.90 ms |
| Deno | `deno run hello.js` | 6.31 ± 0.30 ms |

Hello-world serving with `wrk -t12 -c256 -d10s --latency`. Each server ran on the same 24 logical CPUs, `wrk` on 24
others.

| Runtime | Requests/s | p50 latency | p99 latency |
| --- | --- | --- | --- |
| Bun | 156,974 | 1.60 ms | 1.80 ms |
| Elide | 635,510 | 0.38 ms | 0.59 ms |
| Deno | 163,511 | 1.54 ms | 1.58 ms |

Each server used its defaults: Bun and Deno serve on one thread, Elide on several.

Versions, setup, and recordings: [Benchmarks](https://elide.help/docs/benchmarks).

## Strengths

- `elide serve --contexts=auto server.ts` runs several copies of the app, sized from the CPU cores, on Linux.
- Flags restrict filesystem, network and subprocess access and limit resources; see [Security model](#security-model).
- The same binary runs WebAssembly, compiles and runs Java and Kotlin, and runs Python after `elide setup python`.

## Weaknesses

- Node-API compatibility is 86.8% and WinterTC 95.9% on their test suites.
- `node:http2`, `node:cluster`, `node:inspector` and `node:wasi` throw `ERR_UNKNOWN_BUILTIN_MODULE`.
- `https.createServer` throws `ERR_HTTPS_SERVER_UNSUPPORTED`, and there is no `WebSocket` global.
- No macOS Intel build; macOS releases are Apple Silicon only.

## Security model

Bun has no permission model. Elide allows everything too, until you pass a flag.

| Flag | Effect |
| --- | --- |
| `--sandbox` | Deny filesystem access; network and subprocesses stay allowed. |
| `--allow-read[=PATHS]`, `--allow-write[=PATHS]` | Allow reads or writes, everywhere or at the listed paths. |
| `--allow-net[=HOSTS]` | Allow network access, to every host or only the listed ones. |
| `--allow-run[=CMDS]` | Allow subprocesses, any or only the listed commands. |
| `--deny-net=HOSTS`, `--deny-run=CMDS` | Deny hosts or commands even when allowed. |
| `--fs-audit` | Log each filesystem decision to stderr. |
| `--limit=workers=N`, `--limit=fds=N` | Limit live workers and open `node:fs` handles. |
| `--max-mem=SIZE` | Limit the heap size. |
| `--timeout=DURATION` | Stop the run after `DURATION` with exit `124`. |

```bash
elide --allow-read=. --allow-net=localhost --allow-run=git app.ts
```

A denied call names the flag to add:

```text
TypeError: fetch to 'example.com:443' is not permitted; grant it with --allow-net=example.com
```

`--sandbox=trusted` is the only available profile. See [Sandbox and Limits](https://elide.help/docs/sandbox).

## Next steps

- [Installation](https://elide.help/docs/installation)
- [JavaScript and TypeScript](https://elide.help/docs/web)
- [Sandbox and Limits](https://elide.help/docs/sandbox)
