Skip to Content
Runtimes

Runtimes

Tynd ships two backend runtimes from the same TypeScript source. Switch with one config line:

tynd.config.ts
export default { runtime: "full", // or "lite" }

This page focuses on the JS surface. For the architectural difference (subprocess vs in-process), see Runtime Modes.

Default to lite

Most desktop apps only need:

  • Web standards (fetch, WebSocket, EventSource, URL, Blob, TextEncoder, crypto.subtle.digest, …)
  • Tynd OS APIs (fs, http, sql, process, …)

A ~6.5 MB binary with no Bun to download is a real UX win. Lite doesn’t silently misbehave on the features it doesn’t expose — they’re absent, and your code either runs unmodified or fails fast.

Switch to full when

  • Your dep graph contains an npm with native bindings you can’t replace (sharp, better-sqlite3, canvas, bcrypt-native, rocksdb).
  • You have a CPU-bound JS hot path profiled as the bottleneck — JSC JIT is often 10-100× faster than QuickJS interpretation.
  • You need HTTP/2 or HTTP/3 client (lite’s fetch is HTTP/1.1 only via the HTTP client).
  • You need full Intl.* (DateTimeFormat, Collator, Segmenter, RelativeTimeFormat).
  • You need dynamic import(path) at runtime — lite ships a single eval’d bundle.
  • You specifically depend on Bun.* / node:* APIs.

JS surface parity

Featurelitefull
ES2023 language (Promises, classes, Proxy, BigInt, Maps/Sets)
fetch + Request / Response / Headers✓ HTTP/1.1✓ HTTP/1/2/3
ReadableStream (fetch body)
WritableStream / TransformStream / CompressionStream
Response.clone() / Request.clone()✗ throws
Streaming upload backpressure✗ drained first
WebSocket
EventSource
AbortController / AbortSignal / AbortSignal.timeout
crypto.getRandomValues / crypto.randomUUID
crypto.subtle.digest (SHA-256/384/512)
crypto.subtle.sign / verify / importKey — HMAC
crypto.subtle AES / RSA / ECDSA
TextEncoder / TextDecoder
URL / URLSearchParams
Blob / File / FormData
atob / btoa
structuredClone (no transfer list)
structuredClone with transfer list✗ throws
performance.now()
console.log/info/warn/error/debug
setTimeout / setInterval / queueMicrotask
Bun.*, Deno.*, node:*
Buffer (Node global)
process.* (Node global)
Dynamic import(path)
SharedArrayBuffer / Atomics / WeakRef / FinalizationRegistry
Chrome DevTools inspector
Full Intl.* (DateTimeFormat, Collator, Segmenter, RelativeTimeFormat)✗ stub✓ ICU

Tynd OS APIs — identical on both runtimes

All 26 OS APIs are Rust-backed and work the same way:

app, tyndWindow, monitors, dialog, clipboard, shell, notification, tray, menu, shortcuts, fs, path, os, process, sidecar, store, sql, http, websocket, terminal, workers, compute, keyring, autolaunch, singleInstance, updater.

See the API reference.

Size + startup

litefull
Binary (Windows x64 release)~6.5 MB host + packed assets~6.4 MB host + ~37 MB Bun (zstd)
Typical shipped app~8-10 MB~44 MB
Cold startsub-50ms~200-500ms (spawns Bun)

How to do X in lite

TaskUse
Read / write a filefs.readText / fs.writeText
Watch filesfs.watch
Hash / RNG bytescompute.hash / compute.randomBytes
Spawn subprocessprocess.exec
Bundled binary (ffmpeg, etc.)process.exec(await sidecar.path("ffmpeg"))
Read env varsos.env("API_KEY")
Persistent k/vcreateStore(ns)
Embedded SQLitesql.open(path)
WebSocketnew WebSocket(url) or websocket.connect
HTTPfetch(url) or http.request
File pickerdialog.openFile
Tray + menutray, menu
Notificationnotification.send
PTY terminalterminal.spawn
Isolated workerworkers.spawn

What full offers that lite doesn’t

CapabilityFull onlyWorkaround in lite
JIT performance for CPU-bound JSMove hot paths to compute, workers, or a sidecar
npm with native bindings (sharp, better-sqlite3, canvas, …)Pure-JS alternative (see below) or switch to full
Bun.*, Deno.*, node:*Tynd OS APIs or pure-JS
Buffer (Node global)Use Uint8Array — every Tynd API accepts it
process.env / process.exitos.env(), app-lifecycle handlers
Raw TCP / UDP sockets, HTTP server, DNS lookupNot exposed in lite yet
HTTP/2, HTTP/3Server must serve HTTP/1.1 fallback
AES / RSA / ECDSA in crypto.subtle@noble/ciphers, @noble/curves
Password hashing (argon2id, bcrypt)@noble/hashes/argon2, bcryptjs
Full Intl.*date-fns / dayjs / i18next
Dynamic import() at runtimeBundle all modules at build time
SharedArrayBuffer / Atomicsworkers with message passing

Pure-JS alternatives (lite-friendly)

MissingLib
AES, ChaCha20@noble/ciphers
RSA, ECDSA, Ed25519@noble/curves
argon2id@noble/hashes (argon2 module)
bcryptbcryptjs
gzip / deflatefflate
brotlibrotli-dec-wasm
streams polyfillweb-streams-polyfill
Intl.DateTimeFormatdate-fns / dayjs
JWTjose
OAuthoauth4webapi
Markdownmicromark / marked
YAMLyaml
Last updated on