Choosing a native layer for Capture
Dropbox Capture, the team's visual communication tool for screen recordings, video messages, screenshots, and GIFs, was designed around a simple premise: users should be able to share their work without onboarding friction. That simplicity extends to the engineering side, where the team's "Margherita pizza" principle pushes them to keep the stack as lean as possible.
Electron and Node gave the team a fast path to a cross-platform TypeScript app for macOS and Windows. The harder question was the third ingredient: how to call native OS-level code simply and reliably. The team wanted a single codebase that could target both platforms without duplication, better error handling, and tighter control over screen capture and recording features. After evaluating the options, they landed on Rust.
Rust was already well established inside Dropbox — it powers the sync engine in the desktop client, file compression tooling, crash reporting infrastructure, and parts of Magic Pocket storage. For Capture, a custom Rust library delivered higher-quality screen recording (from 720p up to 4K), faster screenshot and recording sharing, and significantly improved error handling.
Why the third-party library approach broke down
Capture started as an internal Hack Week project, where speed mattered more than architectural elegance. Early versions leaned on several third-party libraries for screenshots, GIF processing, and other OS interactions. Those libraries were mostly shell-based applications: Capture would spawn a process and parse its stderr or stdout output. That meant launching an application for each task — or worse, keeping one running in the background just to await commands.
The brittleness showed up in error handling. Every line of shell output had to be parsed manually; a failed parse was treated as an error, and the underlying native failure was often masked. Monitoring and debugging became a guessing game.
From a developer's perspective, the libraries created friction in other ways. Even within a single cross-platform library, macOS and Windows APIs diverged, complicating development for both platforms. Some libraries were well maintained but missing features; others had everything the team wanted but were poorly maintained. And when a bug needed fixing inside a third-party library, an engineer had to learn how to build that library from scratch — one such effort to fix a single parsing bug in the Windows screen recording library cost hours of development time.
Building up the Rust library incrementally
The team started small. The first Rust experiment was porting activate-windows, a feature that let Capture bring a specific window to the foreground and record only that window. Originally macOS-only, the feature was ported to Rust on macOS quickly, then to Windows for the first time. That early win proved the approach worked.
As the team's confidence grew, more features moved into the custom Rust library. The benefits accumulated across several dimensions:
- No process overhead. Using Neon-bindings, TypeScript can call native OS code directly, eliminating the need to spawn shell applications. Screenshots, previously asynchronous due to the round-trip to a shell process, became immediate.
- Better error handling. With capture code living inside a single library and a consistent API across macOS and Windows, the team added robust logging and monitoring. No more interpreting shell output — the codebase offered clear visibility into actual app behavior.
- More control. Owning the library meant fixes shipped faster. A persistent instability when capturing with more than three screens was resolved more easily with all code in one place, and the build pipeline became simpler across platforms.
- A smaller footprint. Dropping third-party dependencies shrank the app. On macOS alone, around 17MB of Swift libraries became unnecessary after rewriting those capabilities in Rust. Calling functions on demand instead of keeping shell applications resident reduced memory usage as well.
- New features. The Rust migration unlocked functionality that hadn't existed on both platforms. Beyond bringing window activation to Windows, the team added a new crop tool, redesigned recording controls, new recording types (audio-only or camera-only), and higher recording quality up to 4K.
The road ahead
The team was surprised by how quickly Rust paid off. Within a few weeks they were shipping Rust code to production, aided by Dropbox's internal community of Rust engineers. For new hires, the learning curve is shorter than it used to be: rather than wrestling with multiple external libraries, a single document explains how to build everything with one command.
Migration is ongoing. The macOS screen recorder has already been rewritten in Rust, with a Windows recorder rewrite in progress. GIF creation and other OS-level integrations are also moving into the in-house library. The team is particularly interested in the maturing Rust ecosystem on Windows, which recently reached v0.21.0 in its official crate.
This isn't an all-or-nothing effort. The Rust library is configured so Capture can still fall back to the old shell process approach for third-party libraries when needed. That lets the team choose deliberately which features to rewrite and when — and keeps the door open if a future migration doesn't pan out. So far, the results have justified the enthusiasm.



