Back to BlogTooling

Deno 2.9 Ships deno desktop: Native Apps Without Electron and a 17ms Cold Start

Deno 2.9 lands deno desktop for shipping native apps from your web stack with no Electron overhead — plus a 2x cold-startup improvement to 17ms, CSS module imports, and lockfile migration from npm, pnpm, yarn, and Bun.

DenoDesktop AppsJavaScript RuntimeCSS ModulesPerformance
Deno 2.9 Ships deno desktop: Native Apps Without Electron and a 17ms Cold Start

Deno 2.9 dropped on June 25, and the headliner isn't a stability fix or a minor API bump — it's deno desktop, a way to ship native desktop apps from your existing web stack with no Electron overhead and a single output binary.

That's paired with a 2x cold-startup improvement (down to 17ms from 34ms), CSS module imports, and first-class lockfile migration from npm/pnpm/yarn/Bun. Busy release.

deno desktop: Web Stack, Native Binary, No Electron

The pitch is direct: you already have a web project. deno desktop build auto-detects your framework — Astro, React, SvelteKit, plain HTML — compiles it, and drops a self-contained binary. Users double-click it. No runtime to install, no 200MB Electron base, no separate update mechanism.

Under the hood, the binary starts a local Deno server and points the operating system's native WebView at it. On macOS that's WKWebView, Windows gets WebView2, Linux gets WebKitGTK. Server-side code still runs — it's not just a static bundle jammed in a window.

Compare this to Electron's model: Electron ships Chromium (90–120 MB compressed) plus a full Node.js runtime plus your app, all bundled together. deno desktop uses whatever WebView the OS already has, so a basic app can land in single-digit MB.

The obvious tradeoff is rendering consistency. Electron guarantees the same Chromium version everywhere; native WebViews vary by OS and update cadence. If you're shipping to enterprise Windows environments where WebView2 might lag, you need to test carefully. For developer tooling, internal apps, or anything targeting reasonably modern consumer systems, the OS WebView is fine and the size tradeoff is compelling.

One thing worth noting: this isn't a new category. Tauri has been doing OS-native WebView desktop apps from web tech for a few years. But Tauri requires Rust for anything backend-adjacent, which is a meaningful barrier. deno desktop gives you TypeScript end-to-end and requires nothing beyond Deno itself. That's a different audience.

17ms Cold Start

Deno 2.9 lands a **2x cold-startup improvement**: from 34ms to 17ms. Sounds small until you're running Deno as a CLI tool, an edge function, or a Lambda handler where startup latency shows up directly in p50 response times.

At 17ms, Deno is in the "instant" range for a JavaScript runtime. This is the kind of improvement that makes you actually want to write CLI scripts in it instead of reaching for a Go binary just to get fast startup.

Memory under load improved alongside startup time. Peak RSS dropped **2.2x** on real-world workloads, and **3.1x on 1MB body payloads**. If you're running Deno in containers with tight memory limits, those numbers translate directly to fewer OOMs and smaller instance sizes without changing a line of application code.

CSS Modules

import styles from "./Button.module.css" with { type: "css" };
document.adoptedStyleSheets = [styles];

CSS module imports are now natively supported, using the with { type: "css" } import assertion from the CSS Module Scripts standard — the same syntax Chrome ships. No bundler step required.

What you get back is a CSSStyleSheet you can adopt into a document or a shadow DOM directly. This is particularly useful inside deno desktop apps, where scoped component styles without a full Vite/webpack pipeline become a realistic option. Write a component, import its CSS module, adopt the stylesheet — done.

Lockfile Migration from npm/pnpm/yarn/Bun

# Drop into a project that already has package-lock.json, pnpm-lock.yaml, etc.
deno install

deno install now reads your existing lockfile directly — package-lock.json, pnpm-lock.yaml, yarn.lock, bun.lockb. It populates Deno's own lock from it, so your resolved dependency tree stays identical through the migration. No manual version reconciliation.

This is a pragmatic move. Teams don't adopt a new runtime by committing to a full migration upfront — they try it on one script or one service first. The lockfile friction was a real barrier to even that minimal evaluation. Removing it lowers the cost of "let's just see" to effectively zero.

Happy Eyeballs v2 and Fetch Priority

Two smaller additions that matter in networking code:

**Happy Eyeballs v2 (RFC 8305)** races IPv6 and IPv4 connections to dual-stack hosts simultaneously, picking whichever responds first. Browsers have done this for years. Deno 2.9 implements it properly at the runtime level.

On networks where IPv6 is unreliable — common in corporate and VPN environments — connections that previously timed out before falling back now succeed in under 100ms instead of 20+ seconds. This isn't visible in code; it just makes your outbound HTTP more reliable on mixed networks.

**Fetch priority** also lands in this release. fetch() now accepts the priority member from the Fetch standard:

const critical = await fetch("/api/user", { priority: "high" });
const analytics = await fetch("/api/events", { priority: "low" });

Browsers have had this for a while. Deno picking it up means you can share fetch utilities between client and server code and get consistent priority behavior in both environments — no more platform-specific wrappers around fetch calls just to get priority hints.

Worth Upgrading?

deno desktop alone makes this a meaningful release if you've been looking for a lightweight Electron alternative that doesn't require learning Rust. The cold-start and memory improvements matter for anyone using Deno in production at any scale. And the lockfile migration support makes it genuinely easier to pilot Deno on an existing npm project without committing to a full rewrite of your dependency setup.

If you're on Deno 2.x already: deno upgrade and you're done. If you're evaluating Deno for the first time, the migration story is now significantly less painful than it was six months ago.

---

*Sources: Deno 2.9 release blog · GitHub release notes · InfoWorld coverage*