Skip to content
Wordstack.

HomeTopics

Ship a desktop app without drowning in Electron

· 7 min read · Wordstack

Tauri, Electron, and a PWA are three different products. Here is how to pick one so you ship a desktop app instead of an Electron science project.

A laptop on a desk showing a dark code editor, with a monitor and headphones behind it

Photo by Christopher Gower on Unsplash

Electron did not become the default desktop stack because it is elegant. It became the default because web developers could ship a window that ran their existing JavaScript, and users would install it if the product was good enough. That deal still holds. The bill is just more obvious than it was in 2018: a chat client that uses a gigabyte of RAM to draw a list, auto-updates that feel like a second product, and a "hello world" that is already a small operating system.

If you are an indie developer or a small team, the question is not "is Electron bad." The question is whether you need it, and what you are willing to own if you do not.

This comparison is Tauri versus Electron versus a PWA. Those are the three answers that actually ship. Native Swift or Kotlin is a fourth answer if you already live there. If you are reading Wordstack, you probably do not.

What you are actually shipping

A desktop app is not a framework. It is an installable window, a process model, an updater, OS permissions, and a support surface when a user's GPU driver is from another life.

Before you pick a stack, write down the parts you cannot fake:

  • Must it run offline as a first-class mode? A PWA can, but only if you design for it. Most teams do not.
  • Does it need a local sidecar? Shelling out to ffmpeg, a database, or a CLI you already wrote is a different product than a website in a window.
  • Who installs it? Developers will tolerate a 120 MB download. Designers and relatives will not.
  • Which OS is real? "It is cross-platform" often means "it is okay on macOS and we will look at Windows after launch."

If you cannot answer those, you will pick Electron because it feels like the safe default. Sometimes it is. Often it is just the default.

Electron: the tax you can explain

Electron embeds Chromium and Node. You write the UI in the web stack you already know. Native modules exist. The ecosystem is huge. Discord, Slack, VS Code, and a thousand worse apps are proof that this ships.

The tax is not theoretical:

  • You ship a browser. Users pay for it in disk and RAM even when your UI is a settings form.
  • The main process is a real backend. If you treat ipcRenderer like fetch, you will invent security holes.
  • Auto-update, code signing, and notarization are a product. Budget a week the first time, then a standing chore.

Choose Electron when at least one of these is true:

  • You need Node APIs or a specific native module in the desktop process, not in a rewrite.
  • You are embedding a large existing web app and cannot rebuild the bridge.
  • Your team can debug Chromium issues and refuses to own a Rust toolchain.
  • You need Windows integrations that the webview-of-the-week still handles poorly.

Do not choose Electron because "the other apps in our category use it." That is how you inherit their RAM usage without inheriting their revenue.

A responsible Electron app is possible. It looks like: one window, a tight preload, no nodeIntegration, a small set of IPC channels, and an updater you have actually tested on a stale machine. If that paragraph already feels like a second job, you are not in love with Electron. You are in love with staying in JavaScript.

Tauri 2: a web UI with a smaller machine underneath

Tauri takes the other side of the bet. The UI is still web. The shell is Rust. The webview is the one the OS already has. The binary can be small enough that you stop apologizing for the download.

Tauri 2 is the version to talk about. The 1.x era was easy to dismiss as "promising." The current one is what you should evaluate if you are starting now: a clearer app model, mobile targets if you want them later, and a plugin system that is less of a scavenger hunt.

You should want Tauri if:

  • The UI is a web app you control, not a pile of Node-only packages that assume fs in the renderer.
  • You care about installer size and idle RAM.
  • You can keep a Rust toolchain working on the machines that build releases.
  • Most native needs are files, notifications, a tray icon, a shell command, or a small sidecar.

You should hesitate if:

  • Your "desktop app" is secretly a Node server with a UI glued on. Porting that to Rust commands is a rewrite, not a config change.
  • Nobody on the team will read a compiler error that is not JavaScript. The first code-signing issue will stall the launch.
  • You need a Chromium-identical renderer on every OS. System webviews are better than they used to be. They are not one browser.

The honest Tauri cost is not "learn Rust." You can ship a lot with the JS bindings and a few audited commands. The cost is the foreign build: targets, signing, webview versions on old Windows, and plugins that are almost official. That is still less surface than shipping Chromium, but it is not npm run make with no leftover thoughts.

A good first Tauri project is a local tool: a tiny GUI over a CLI you already trust, a markdown previewer, a local-first notes app, a build dashboard. A bad first project is "Slack, but ours."

PWA: the desktop app you might not need to ship

A Progressive Web App is the option teams skip because it does not feel like shipping. Sometimes that is the point.

If your product is already a website, "install this app" can mean: a manifest, an icon, a service worker you do not half-implement, and a window that opens without browser chrome. On desktop Chromium that path is real. On iOS it is more limited. On users who never click Install, it is still just a bookmark.

Use a PWA when:

  • Offline is optional or you can do it properly with a boring cache strategy.
  • You do not need a tray icon, a global shortcut, or a process that runs after the window closes.
  • Distribution through the browser is acceptable. You are not trying to win a Store badge in week one.
  • You would rather spend the month on the product than on notarization.

A PWA is not a consolation prize. For many SaaS tools — dashboards, editors that live on a server, anything that is useless without an account — a desktop wrapper is how you get a Dock icon and a second update channel. That is not a strategy. That is merch.

The failure mode is the fake PWA: no offline story, a service worker that caches the marketing site, and a prompt that nags people who just wanted the URL. If you cannot explain what install adds, do not add it.

A decision you can make in an afternoon

NeedPWATauriElectron
Small downloadYesYesNo
Stay in JS/TS onlyYesMostlyYes
Local binaries / sidecarsNoYesYes
Deep Node desktop ecosystemNoNoYes
Works without a storeYesYesYes
Feels "native" to a picky userSometimesCloserFine if the UI is good

Walk it in this order:

  1. Can the product be a website with an install prompt? If yes, ship the PWA. Measure whether anyone asks for more.
  2. If you need a real binary, can the privileged work be a short list of commands or a sidecar? Start with Tauri.
  3. If the desktop process is a Node program, or the team cannot own Rust builds, take Electron and keep the surface small.

Do not prototype in Electron "because we can always slim down." You will not slim down. You will add another IPC channel.

A shipping path that is allowed to be boring

Whatever you pick, the launch checklist is the same and nobody puts it in the framework docs:

  • Sign the binary on day one, not the day you tweet the download.
  • Test the updater on a machine that is two versions behind.
  • Decide what happens when the user is offline. "Spinner" is not a decision.
  • Write down the OS versions you actually support. "Latest" is not a support policy.
  • Keep a crash log you can ask for. Desktop users do not open DevTools for you.

If you are building an indie desktop app in 2026 and you do not have a reason to embed Chromium, do not embed Chromium. Tauri is the grown-up default for a web UI that needs a real window. A PWA is the grown-up default for a web UI that does not. Electron is the grown-up default for a Node program that happens to have a window.

The stack that wins is the one that lets you stop thinking about the stack. Pick it, ship the window, and go back to the product.

Related