Why Dropbox moved updates out of the client

Dropbox’s desktop client originally handled automatic updates through normal file sync. The server would include an update directive in metadata — version and checksum — and the client would fetch the payload, validate it, swap its own files, and restart. The approach worked, but only if the client was running and healthy. Any bug elsewhere in the application could stall updates, and a fully broken client could not repair itself.

The company solved that problem on Windows in 2014 by adapting Google’s Omaha project, which runs as a separate process. Last year, Dropbox went looking for an equivalent on macOS. Google’s UpdateEngine, a sort of “Omaha for Mac,” was considered but rejected: the last code drop was from 2008, and it would not compile cleanly with modern Xcode. Other candidates were in-process only, supported a single application, or required macOS Sierra — Dropbox still supports much older OS X releases.

The decision was to build a standalone updater from scratch. That allowed the team to design for their exact needs rather than retrofit features, as they had done with Omaha.

What the updater had to do

The design goals were straightforward:

  • Safety: users must only ever run code that has been properly verified.
  • Speed: updates should reach users as quickly as possible.
  • Simplicity: clean design, clean implementation, thorough unit tests.
  • Separation of concerns: how an update is delivered shouldn’t be coupled to how it’s installed.
  • Error handling: common failures, especially network issues, must be handled gracefully.
  • Logging: rich logs to catch quality degradation early.

Architecture: DropboxMacUpdate

The result is DropboxMacUpdate.app, a separate application written in Objective-C. The team chose ObjC specifically to support systems back to Mac OS 10.7; Swift was not an option. Being a native Apple-language app also let them use OS features directly, unlike the client itself, which is written in Python and would need bridge code for system-level work.

On install, DropboxMacUpdate.app registers with launchd, so it can check for updates periodically without any user action. Every five hours it looks through its registration database for apps, reads each installed app’s version from its path, and sends that to a Dropbox server. If an update is needed, the server responds with the version, a download URL, and the payload’s hash. DropboxMacUpdate downloads the payload and performs the update.

Payload format

At minimum, the update payload is a DMG containing an executable file named .dbx_install at its root. The executable handles everything needed to install the new app version. In practice, the DMG also includes the .app bundle itself, but the format leaves room for other approaches — a payload using diffs, for example. Because DropboxMacUpdate doesn’t know install details, a broken payload simply fails, and the server can point the updater at a different one on the next cycle.

This design draws some inspiration from Google’s UpdateEngine.

Security layers

Distribution integrity is enforced with several checks:

  1. Connections to the server use TLS with certificate pinning, so the updater only ever talks to dropbox.com.
  2. The server supplies a sha256 hash of the payload, which is verified after download.
  3. .dbx_install checks that the app bundle is signed by Dropbox before copying it into place.
  4. On macOS 10.12 and later, the DMG payload is also signature-verified. Earlier OS X versions lack the APIs for DMG signature validation.

The updater may run at any time, so it can find itself trying to update a live application. The .dbx_install executable locates the running app and sends it a Darwin notification asking it to quit. The client receives that notification, checks it isn’t showing any UI, completes active sync work, and exits cleanly. .dbx_install then replaces Dropbox.app atomically and relaunches it. If the application is showing UI, the updater waits rather than interrupt the user.

Rollout

Beta users have been running DropboxMacUpdate for the past few months, receiving updates at greater speed — the infrastructure has handled roughly 3,000 client updates per second at peak. The company is now shipping the updater to all macOS users as of desktop client version 21.