The problem
The Dropbox desktop app runs on Windows, macOS and Linux, and it is written in Python: "over 1 million Python LOCs", in their words. Staying on Python 2 was costing them in three ways:
- Missing language features: they wanted "Type annotation syntax" and "Coroutine function syntax" (
async/await). - An ageing toolchain: "Python 2 still technically requires Visual Studio 2008. This version is no longer supported by Microsoft."
- Operating-system features out of reach: newer platform APIs, such as Windows Runtime and macOS FinderSync extensions, were hard to use from Python 2.
What they did
They didn't switch everything on one day. The work started in 2015, and the app was rebuilt so it could carry both interpreters at once: a bootstrap library let them ship "both Python 2 and Python 3 'packages,' complete with bytecode and extensions, side by side."
With both in the same app, Python 3 became a switch they could turn on for some users and off again. They widened it in stages: first for Dropbox employees, then the Beta population, then the Stable channel.
The rule that kept it safe
One policy did most of the work: "all bugs identified as migration-related be fully investigated and corrected before expanding the number of exposed users." A problem found at 1% of users was fixed at 1%, not discovered at 100%.
The part any team can copy
You don't need a desktop app to use a staged rollout. The core of it is a stable way to decide who gets the new path, so the same user always lands on the same side:
import hashlib def in_rollout(user_id: str, percent: int) -> bool: bucket = int(hashlib.sha256(user_id.encode()).hexdigest(), 16) % 100 return bucket < percent users = ["ada", "linus", "grace", "hedy", "margaret", "alan"] print([u for u in users if in_rollout(u, 50)]) print(in_rollout("ada", 50) == in_rollout("ada", 50)) # same answer every time
['hedy', 'alan'] True
Only two of six at 50% is normal for a small sample; over thousands of users it evens out. Raising percent only ever adds users: anyone already in stays in, so widening the rollout never flips someone back and forth between old and new code.