Where the languages meet  / field guide
Practitioner field guide · Integration & APIs · 2026-10-15

Where the languages meet: ten years of Dropbox, read from its own repositories

Between 2014 and 2026 Dropbox moved logic out of Python, into and back out of shared C++, and into Rust, while keeping a public API that six SDKs in six languages are regenerated from. This guide reconstructs the decade from the artefacts Dropbox published (repositories, slide decks, issue threads and registry records) and asks one question of each change: where did the languages meet, and what did that seam cost when something underneath it moved?

41 ledger rows 31 evidence cards 5 incident records Evidence through October 2026 Read: 29 min
01

The territory: a company that kept changing languages

The problem, stated without any language's name: a growing engineering organisation keeps discovering that the language it wrote a component in is wrong for that component, and has to decide where the boundary between old and new code will sit, who generates it, and what crosses it.

Jan 2026
Every Python SDK older than 12.0.2, and every Java and .NET SDK older than 7.0.0, stopped working against the API servers
5 places
Extra code per function before Dropbox generated its mobile C++ bridge
88 days
From a crafted-JPEG denial-of-service report to the archive of Lepton's public C++ codec
0 of 862
mypy commits from a Dropbox address in 2025, against at least 321 of 1,442 in 2015; the project kept going

Dropbox is a useful company to read this way because it made every kind of language-boundary decision in public, and then reversed several of them in public. In 2014 two of its engineers told CppCon that the mobile Camera Uploads feature had "shipped 4 months apart" on iOS and Android, built by "~3 engineers", and that the answer was a shared C++ core behind a generated bridge called Djinni. In the same year a separate team started an interface definition language, first called Babel and later Stone, to describe the public HTTP API once and generate clients from it. Inside the company the server and desktop code was Python, and Dropbox paid for a large share of mypy's early development to type that Python in place rather than rewrite it. In 2016 the storage system started moving bytes through Rust.

Ten years on, the record sorts these bets cleanly. The schema-described network boundary is alive and automated: a bot updated the API specification on 9 October 2026 and regenerated five of the six official SDKs the same day. The in-process bridge was declared unmaintained in April 2019. The typing work became a language standard (PEP 484) and a compiler (mypyc), and the temporary scaffolding Dropbox built around it was left to stop. The C++ JPEG codec was archived after a denial-of-service report, and the successor its deprecation notice recommends is a Rust port whose stated reason is safety.

The surprise

The part of the API boundary that broke every old client was the part the schema did not describe. Stone's own design note says third-party integrations "may never be updated" and codifies which spec changes are safe for them; Dropbox followed it for a decade. But the Python SDK's first commit, on 15 June 2015, also shipped a pinned CA bundle, trusted-certs.crt, and the Java SDK pinned too. Nothing in the specification language could see that file. The pin was removed in April and May 2024, and in January 2026 every Python, Java and .NET SDK released before the removal stopped working.

Figure 1 · A decade of seams, dated from the artefacts

2014Babel IDL, laterStoneDjinni shown atCppCon2015-16API v2 spec andSDKs with pinnedCA fileLepton in C++, Rustfor Magic Pocket2017-19Stone compatibilityrulesmypy compiled bymypycDjinni no longermaintained2020-23Automated specupdatesLepton archivedafter DoS report2024-26SDKs drop pinnedtrust anchorsPre-2024 SDKs stopworkingDropbox seams, 2014 to 2026
2014Babel IDL, laterStoneDjinni shown atCppCon2015-16API v2 spec andSDKs with pinnedCA fileLepton in C++, Rustfor Magic Pocket2017-19Stone compatibilityrulesmypy compiled bymypycDjinni no longermaintained2020-23Automated specupdatesLepton archivedafter DoS report2024-26SDKs drop pinnedtrust anchorsPre-2024 SDKs stopworkingDropbox seams, 2014 to 2026
The seams opened in 2014 to 2016 and closed or hardened in 2019 to 2026; the only one still growing is the schema-generated API boundary. Dates are first commits, notices and releases from the repositories and registries in the evidence wall.
Diagram source

Scope. This guide covers the boundaries between languages and between Dropbox and the code that calls it: the mobile bridge, the API description language and its SDKs, the typing of Python, and the move of byte-handling code to Rust. It does not cover Magic Pocket's storage design, the sync engine's internals, Dropbox's data centres or its costs, because none of that is reachable from this session's corpus (GitHub and package registries only; dropbox.tech, USENIX and video hosts did not resolve). Where a reason for a decision appears only in a blog post this session could not fetch, the guide says the reason is not in the record rather than supplying it.

02

Four seams, and what each one carried

Reconstructed from the artefacts, Dropbox's languages met in four kinds of place. They differ in one property that turned out to decide their fate: whether the thing crossing the seam was described by a schema, or was shared code.

Figure 2 · Where Dropbox's languages met, 2014 to 2026

4 · Bytes into Rust

archived 2023

Lepton C++ codec

Rust: storage, sync,
Brotli, protobuf

3 · Types in Python

Python code

mypy, PEP 484

mypyc compiled output

2 · In-process bridge

Djinni IDL

JNI and Obj-C++ glue

Shared C++ core

1 · Network schema

bot, every few days

not in the schema

.stone spec files

Stone generators

6 SDKs: Python, Java, JS,
Swift, Obj-C, .NET

Hand-written pinned CA file

4 · Bytes into Rust

archived 2023

Lepton C++ codec

Rust: storage, sync,
Brotli, protobuf

3 · Types in Python

Python code

mypy, PEP 484

mypyc compiled output

2 · In-process bridge

Djinni IDL

JNI and Obj-C++ glue

Shared C++ core

1 · Network schema

bot, every few days

not in the schema

.stone spec files

Stone generators

6 SDKs: Python, Java, JS,
Swift, Obj-C, .NET

Hand-written pinned CA file

Solid boxes are seams still maintained in 2026; dashed are retired or handed off. The one hand-written component inside the generated SDK, the pinned CA file, is the part that broke clients. Reconstructed from Stone's design notes, the CppCon 2015 Djinni slides and the pb-jelly README.
Diagram source

Seam 1 · The network boundary, described by a schema

Stone's first commit is dated 21 July 2014, and within a month its authors were merging from a repository named babelsdk; the Python SDK's first commit in June 2015 still ships files called babel_serializers.py and babel_validators.py. The specification itself lives in its own repository, dropbox-api-spec, as a set of .stone files (files.stone, sharing.stone, auth.stone and so on), first committed on 19 June 2015. Each SDK pulls it in as a git submodule. Since October 2020 SDK updates have arrived as commits titled "Automated Spec Update", first pushed by an engineer, then by a DropboxBot account (40 such commits in the Python SDK), and since 29 July 2026 by a pair of bots: one commits to the spec, the other regenerates each SDK. The spec repository took 39 commits in 2026 to mid-October.

What makes this seam durable is written down. Stone's evolve_spec.rst, added on 2 March 2017, frames compatibility as a sender and a receiver either of which may be newer, and gives the reason plainly: "The owner of the API does not have control over 3rd parties that have integrated their software at some point in the evolution of the interface. These integrations may never be updated." It then lists the changes that break an old receiver (removing a struct field, changing a field's type, adding a tag to a closed union) and the ones that do not (adding a route, adding an optional field). That list is the whole contract. Note what it is about: fields, unions and routes. It says nothing about transport or trust, and section 04 shows why that gap mattered.

Seam 2 · The in-process bridge, generated but shared

The mobile seam made the opposite choice on the property that matters. The 2015 Djinni talk states the design principle in two lines: "Method calls pass control between languages. Not serialized RPC." One interface written in Djinni's IDL produced C++, Java and Objective-C abstract classes plus "(4 files) JNI bridging" and "(4 files) Objective-C++ bridging". The generator removed the boilerplate the 2014 team had complained about (five extra places to touch per function), but the seam still sat inside one process, so a defect could live on either side of it, in either toolchain, and the 2014 Allain and Twyman deck already listed "General: inconsistent debugging" among the costs. The measured wins in 2014 were real and platform-specific: on a Nexus 4, "~500k objects: 500 MS GC!", and holding 30,000 photos in C++ made "300k objects disappear from the GC's view". Those numbers describe Android's 2014 runtime, which matters for reading the reversal.

Seam 3 · Types inside one language

For the server and desktop Python, Dropbox did not move the boundary between languages; it put a new boundary inside the language. PEP 484, created on 29 September 2014 and co-authored by mypy's creator Jukka Lehtosalo, says it is "strongly inspired by mypy" and takes optional annotations "from the idea of gradual typing". Commits to mypy from a Dropbox address went from 116 in 2014 to 321 of 1,442 in 2015 and 297 of 976 in 2016, a floor, since several core developers committed from personal addresses. Around that core Dropbox built scaffolding: pyannotate (2017) inserts annotations from types observed at runtime; sqlalchemy-stubs (2018) supplies stubs and a mypy plugin because "SQLAlchemy uses some Python 'magic'"; mypy-protobuf (2017) generates type stubs from protobuf schemas. Then the annotations became an input to a compiler: mypyc, whose README says "the mypy project has been using mypyc to compile mypy since 2019, giving it a 4x performance boost". PyPI confirms the date: mypy 0.700, uploaded 3 April 2019, is the first release with CPython-ABI wheels, and release 2.4.0 ships 50 compiled wheels out of 52 files.

Seam 4 · Bytes, moved into Rust

Where code parsed or shuffled large volumes of bytes, Dropbox changed the language outright. The pb-jelly README says Dropbox's Rust protobuf generator was "initially written in 2016 to satisfy the need of shuffling large amount of bytes in Dropbox's Storage System (Magic Pocket)", replacing rust-protobuf to avoid serialising twice, and is now used in "our Sync Engine". The Rust Brotli codec started in April 2016 and took 170 of its 387 commits in 2018 from Dropbox addresses. The C++ codec from the same period, Lepton, which compresses JPEGs losslessly "by an average of 22%", did not make the transition, and its end is the clearest single case in the corpus of why the byte seam moved.

Generated from a schema

Stone spec to six SDKs; protobuf to Rust (pb-jelly) and to Python stubs (mypy-protobuf). All three are maintained in 2026.

Evidence: spec bot commit, mypy-protobuf releases

Generated, but sharing a process

Djinni's IDL to JNI and Objective-C++ glue around a shared C++ core. Unmaintained by Dropbox since 11 April 2019.

Evidence: maintenance note commit

Scaffolding meant to stop

pyannotate (last release 2019), sqlalchemy-stubs (last release 2021), dbx_build_tools (last commit 2023). None carries an archive banner; all stopped.

Evidence: pyannotate, sqlalchemy-stubs

03

The decisions that matter, and what flipped them

Five forks, each with the choice Dropbox made, what it gave up, and the condition under which the other branch is right. Where Dropbox's own reason is not in the reachable record, the entry says so.

Decision 1: share mobile logic in-process, or describe it and implement twice?

Chosen, 2014
  • One C++ core behind a generated JNI and Objective-C++ bridge (Djinni).
  • Won because two three-person teams were shipping the same sync logic months apart, and C++ escaped a 2014 Android garbage collector.
Reversed, by 2019
  • Dropbox-addressed Djinni commits fell from 93 of 229 (2015) to 4 of 39 (2017); the maintenance note followed in April 2019.
  • The stated reason is not in the reachable record; the repository gives only "no longer maintained by Dropbox".
Flips when
  • Shared C++ wins while the shared logic is large, stable and performance-bound, and the team cannot staff two platforms. It loses once each platform has its own specialists, because every one of them must now debug across a seam they do not own.

Decision 2: hand-write SDKs, or generate them from a specification?

Chosen, 2014 to 2026
  • An IDL (Babel, then Stone) and a separate spec repository, consumed as a submodule.
  • Compatibility rules written for the case where clients "may never be updated".
Rejected
  • Per-language SDKs written by hand, which is what v1 had.
  • Inferred cost avoided: six SDKs drift apart one route at a time.
Flips when
  • With one or two client languages and a team that owns both ends, a generator is overhead. Past three languages, or with third parties you cannot upgrade, the schema is the only artefact that can carry a compatibility promise.

Decision 3: make the Python safer in place, or rewrite it?

Chosen, 2014 to 2019
  • Gradual typing with mypy, plus inference (pyannotate), library stubs and protobuf stubs; later compilation with mypyc.
  • Every step leaves running code running.
Not chosen for the bulk
  • Wholesale rewrite into Go: godropbox (2014) took 255 of its 318 first-year commits from Dropbox, then tapered to a last module version in June 2023.
Flips when
  • Typing in place is right while the problem is correctness at scale. Where the problem is bytes per second or memory safety on hostile input, annotation does not help and the language must change, which is what Dropbox did for storage and sync.

Decision 4: who parses untrusted bytes?

Ended with
  • Rust for storage, sync and compression (pb-jelly, rust-brotli, fast_rsync); a Rust port of Lepton recommended to public users.
Retired
  • Lepton in C++, archived on 14 February 2023 after a crafted JPEG put its verification step into an infinite loop.
Flips when
  • C++ remains defensible for code that only ever sees bytes you produced. The moment a parser accepts customer files, the maintenance bill includes every fuzzing report for as long as the code is public.

Decision 5: ship trust material inside the client, or defer to the platform?

Chosen, 2024
  • "The SDK no longer provides a CA bundle to verify SSL connections", with a ca_certs parameter for callers who want to pin.
Abandoned after nine years
  • A pinned CA bundle shipped in the SDK package from 2015 (trusted-certs.crt in Python; pinning in Java's standard requestor).
Flips when
  • Pinning in a client you ship is defensible only if you also control when it updates (your own mobile app). In a library that third parties vendor and forget, the pin turns every certificate change into a breaking API change.

Figure 3 · Choosing the seam, as Dropbox's record would choose it

yes

no

correctness

bytes or hostile input

duplicate logic

yes

no

Does the other side ship
on its own schedule?

Network schema plus generators;
nothing hand-written in the client

Is the problem
correctness or bytes?

Gradual types in place;
date the scaffolding's end

Replace the language
at that boundary

Can every engineer
debug both sides?

In-process bridge

Implement twice
against one schema

yes

no

correctness

bytes or hostile input

duplicate logic

yes

no

Does the other side ship
on its own schedule?

Network schema plus generators;
nothing hand-written in the client

Is the problem
correctness or bytes?

Gradual types in place;
date the scaffolding's end

Replace the language
at that boundary

Can every engineer
debug both sides?

In-process bridge

Implement twice
against one schema

Every terminal is a seam Dropbox ran; the right-hand branches are the ones still maintained in 2026. Derived from the five decisions above; the ordering of the questions is this guide's inference, not a Dropbox document.
Diagram source
DecisionChosenRejected or reversedBecauseEvidence
Mobile logicShared C++ via Djinni, 2014Reversed by 2019Reason not in reachable record; Dropbox commit share fell firstdjinni dfb9982
Public API clientsStone spec, generated SDKsHand-written SDKsThird parties "may never be updated"evolve_spec.rst
Server PythonGradual typing, then mypycBulk rewriteRunning code stays runningPEP 484
Byte-handling codeRustC++ (Lepton)Hostile-input fixes outran capacitylepton notice
SDK trust anchorsPlatform store, opt-in pinPinned CA in packageOld pins break on rotationsdk-python #489
04

What broke sat outside the schema

Five incident records, from issue threads, a security report and two README notices. None is a formal postmortem document; Dropbox's public postmortems live on a blog this session could not reach. Read them as the incident trail the repositories kept.

Incident

2016: a pinned CA file that Android parsed to nothing

AssumptionA PEM bundle that Java 7 parses correctly will parse the same way on Android.
What happenedSDK 2.0.4 uploads failed with "Trust anchor for certification path not found". Android would "silently fail parsing the PEM encoded file, omitting the required certificates".
Blast radiusAndroid apps on 2.0.4, 4 to 8 June 2016. Unnoticed earlier because the example's OkHttp requestor did not pin.
Fix2.0.5, released four days after the report.
Design ruleTrust material shipped in a library is code that runs on every platform's parser; test it on each, or do not ship it.
Incident

2016: emailing app owners about a certificate change

AssumptionServer certificates can be rotated without telling clients.
What happenedBecause SDKs pinned, Dropbox wrote to developers whose "logs indicate that you have at least one Dropbox API app" ahead of a switch on 1 August 2016.
Blast radiusNo outage recorded; the cost was a fleet-wide notification and support traffic.
FixNone structural: v2 SDKs already carried the new chain, so the pin stayed.
Design ruleThe first rotation that needs an email is the warning; the second one is the outage.
Incident

January 2026: every pre-2024 SDK stops working

AssumptionThe schema's compatibility rules protect clients that are never upgraded.
What happenedA server certificate change met the CA files pinned inside old SDK packages. Python before 12.0.2 and Java and .NET before 7.0.0 "stopped working in January 2026".
Blast radiusEvery unupgraded integration in three of the six SDK languages. The fixed releases had been available since April to June 2024.
FixPins removed in 2024 (Java PR #537, Python PR #489); README banners added, the Python one merged 5 November 2025.
Design ruleAnything a client package carries is part of the API contract, whether or not your IDL can express it.
Security report

2022: a crafted JPEG hangs Lepton's verification

AssumptionA codec proven on Dropbox's own photo corpus is safe to publish for anyone's input.
What happenedReported by Tenable: a crafted JPEG produced a LEP file whose conversion back "causes an infinite loop", in encode_eobrun.
Blast radiusPublic users of the C++ codec. Dropbox said internal use was not affected.
FixNone in public: deprecation the same day, archive on 14 February 2023, users pointed to Microsoft's Rust port.
Design ruleA public parser of hostile input is a standing security obligation; budget for it or do not publish it.
Design failure

A plugin that could not follow the checker it plugged into

AssumptionA mypy plugin can paper over a library's dynamic "magic" indefinitely.
What happenedSQLAlchemy deprecated its own mypy plugin: it "cannot be maintained across constantly changing releases of mypy" and works only up to mypy 1.10.1. Dropbox's sqlalchemy-stubs, the same stubs-plus-plugin design, last released in January 2021.
Blast radiusEvery codebase type-checking SQLAlchemy 1.x models through a plugin.
FixThe library typed itself: SQLAlchemy 2.0's "fully pep-484 compliant mapping syntaxes".
Design ruleA seam that hooks another tool's internals is coupled to that tool's release cadence; it is scaffolding, so give it an end date.

The sequence below is the January 2026 failure path. It is the most instructive record in the corpus because it was preventable by the company's own written rule and was still not caught, since the rule's vocabulary (fields, unions, routes) had no word for a file of certificates.

Figure 4 · How a 2015 file broke 2026 clients

Dropbox APIserversOld SDK 2015 to2024Third-party appDropbox APIserversOld SDK 2015 to2024Third-party appJun 2015 packageshipstrusted-certs.crtMay 2024 new SDKs drop thebundle, old ones keep itJan 2026 servercertificate chainchangesfiles_uploadTLS handshake, verify againstpinned CAsChain signed by a pinned CAOK, schema-compatibleresponsefiles_uploadTLS handshake, verify againstpinned CAsChain not under any pinned CASSL error before any route iscalled
Dropbox APIserversOld SDK 2015 to2024Third-party appDropbox APIserversOld SDK 2015 to2024Third-party appJun 2015 packageshipstrusted-certs.crtMay 2024 new SDKs drop thebundle, old ones keep itJan 2026 servercertificate chainchangesfiles_uploadTLS handshake, verify againstpinned CAsChain signed by a pinned CAOK, schema-compatibleresponsefiles_uploadTLS handshake, verify againstpinned CAsChain not under any pinned CASSL error before any route iscalled
The schema path (top) stayed compatible the whole time; the trust path (bottom) carried a decision made in the SDK's first commit. Dates from sdk-python f72f99d, PR #489 and the 2026 README.
Diagram source
05

Numbers you can plan against

Every figure below was computed in this session from a repository or a registry, with the date it describes. Commit shares count author addresses containing "dropbox" and are floors.

MetricValueAtContextAs ofSource
Life of the pinned CA file in the Python SDK8 yr 11 modropbox-sdk-pythonAdded 2015-06-15, removed 2024-05-09202441e4b00
Fixed release to forced break~19 monthsPython, .NET12.0.2 on 2024-06-03 and .NET 7.0.0 on 2024-05-22, break in January 2026 (arithmetic)2026PyPI, NuGet
SDK languages that broke3 of 6Python, Java, .NETJS, Swift and Obj-C READMEs carry no January 2026 notice2026-10.NET README
Spec commits in 202639dropbox-api-specJan to mid-Oct; spec bot active since 2026-07-292026-103c363a5
Stone releases on PyPI27stone0.1 on 2016-06-03 to 3.5.5 on 2026-09-232026-09PyPI
JS SDK versions published155npm dropboxLatest 10.47.02026-09npm
Lepton average saving22%LeptonDropbox's claim, lossless on JPEG2016README
Report to archive, Lepton88 daysLepton2022-11-18 to 2023-02-142023#158
Android GC pause, 500k objects500 msNexus 4The 2014 case for C++ on mobile2014CppCon 2014
Djinni Dropbox commit share41% to 10%djinni93 of 229 in 2015; 4 of 39 in 20172017djinni
mypy Dropbox commit share30% to 0%python/mypy297 of 976 in 2016; 0 of 862 in 20252025mypy
mypy speed-up from mypyc4xmypyProject's own claim; compiled since 0.700, April 20192021mypyc README
Rust Brotli, Dropbox share44% to 0%rust-brotli170 of 387 in 2018; 0 of 153 in 20242024crates index

Figure 5 · mypy kept its pace after its sponsor left

mypy commits per year: all vs Dropbox-addressed20142015201620172018201920202021202220232024202520261400120010008006004002000Commits
mypy commits per year: all vs Dropbox-addressed20142015201620172018201920202021202220232024202520261400120010008006004002000Commits
Bars are all mypy commits per year; the line is commits from a Dropbox address, a floor. Dropbox's share collapsed after 2016 while total activity held between 515 and 1,110 commits a year, which is what a seam that became a standard looks like. Computed from python/mypy history; 2026 is January to mid-October.
Diagram source
Read these carefully

The 22% and 4x figures are their projects' own claims and no independent measurement was reachable. Commit shares undercount Dropbox, because engineers commit from personal addresses (mypy-protobuf's maintainer switched from a Dropbox to a personal address in 2021). The nineteen-month lead time is arithmetic on release dates, not a measurement of how many integrations broke; Dropbox has not published that number in any reachable source.

06

The evidence wall

Thirty-one sources, graded. Issue threads and README notices that record a production failure are graded as incidents; there is no blog or paper tier because neither host class resolved from this session.

IncidentDropbox2016-06

dropbox-sdk-java #57: Trust anchor for certification path not found

Android silently dropped certificates from the pinned PEM file in SDK 2.0.4; only one of two requestors pinned, so it escaped testing. Fixed in 2.0.5 four days later.

Carry forwardPinned trust material is platform-specific code; test it on every runtime you ship to.
github.com/dropbox/dropbox-sdk-java/issues/57
IncidentDropbox2016-04

dropbox-sdk-python #60: out of date certificate file in SDK?

A developer quotes Dropbox's email warning of a server certificate switch on 1 August 2016 because SDKs pin; the maintainer confirms v2 needs no action.

Carry forwardIf rotating a certificate requires emailing your API users, the certificate is part of your API.
github.com/dropbox/dropbox-sdk-python/issues/60
IncidentDropbox2026

dropbox-sdk-python README: older versions stopped working in January 2026

The banner states the outcome flatly: SDKs older than 12.0.2 no longer work with the API servers.

Carry forwardA deprecation you cannot enforce becomes an outage on the day the server changes.
raw.githubusercontent.com/dropbox/dropbox-sdk-python/.../README.rst
Security reportDropbox / Tenable2022-11

lepton #158: denial of service with specially crafted JPEG files

A crafted JPEG yields a LEP file whose verification round-trip loops forever. Repository archived 14 February 2023.

Carry forwardThe first hostile-input report is when you learn whether you can afford a public parser.
github.com/dropbox/lepton/issues/158
SourceDropbox2022-11 / 2023-02

lepton README deprecation notice

"We no longer have sufficient resources to adequately support this project"; internal use unaffected; users pointed to a Rust port, Brotli, WebP or JPEG XL.

Carry forwardPublic and internal copies diverge; the public one is retired first.
raw.githubusercontent.com/dropbox/lepton/.../README.md
SourceMicrosoft2026

lepton_jpeg_rust README

"A port of the C++ Lepton JPEG compression tool that was released by DropBox", motivated by "the safety features that Rust has to offer" after "an exhaustive security check on the C++ code".

Carry forwardKeep the format, replace the language at the parser.
github.com/microsoft/lepton_jpeg_rust
SourceDropbox2024-05

dropbox-sdk-python PR #489: Stop providing a hardcoded CA bundle

Removes the bundle, falls back to the platform's verification, keeps ca_certs for callers who want to pin, and drops a runtime dependency on setuptools.

Carry forwardDefault to the platform trust store; make pinning opt-in.
github.com/dropbox/dropbox-sdk-python/pull/489
SourceDropbox2024-04

dropbox-sdk-java PR #537: Remove cert pinning from the SDK

Merged the day v7.0.0 was tagged, with no description; the commits restore an opt-in pin for standard connections.

Carry forwardA breaking change with no written rationale leaves the next maintainer guessing.
github.com/dropbox/dropbox-sdk-java/pull/537
SourceDropbox2015-06

dropbox-sdk-python initial commit f72f99d

The first commit already contains trusted-certs.crt next to the Babel-generated serializers and route modules.

Carry forwardAudit what your first commit put in the package; it may outlive everything else.
github.com/dropbox/dropbox-sdk-python/commit/f72f99d
Design docDropbox2017-03

Stone: Evolving a Spec

Sender and receiver may each be newer; third-party integrations "may never be updated"; explicit lists of breaking and non-breaking spec changes.

Carry forwardWrite the compatibility rules down, then ask what your rules cannot see.
raw.githubusercontent.com/dropbox/stone/.../docs/evolve_spec.rst
SourceDropbox2014-07

Stone history: Babel to Stone

First commit 21 July 2014; merges from a babelsdk repository in August 2014; 27 PyPI releases since 2016.

Carry forwardThe IDL is the longest-lived asset in this corpus; invest in it early.
github.com/dropbox/stone/commit/93373c4
SourceDropbox2026-10

dropbox-api-spec: Update API specification (#138)

A bot has committed .stone changes since 29 July 2026; SDKs consume the repository as a submodule. 39 spec commits in 2026 to mid-October.

Carry forwardPublish the spec as its own versioned artefact, separate from any SDK.
github.com/dropbox/dropbox-api-spec/commit/3c363a5
SourceDropbox2026-10

dropbox-sdk-python: Automated Spec Update (#613)

One of five SDK regenerations on 9 October 2026; the first commit with that title in Python and JS is dated 5 October 2020, pushed then by an engineer.

Carry forwardRegeneration should be boring enough for a bot to do it.
github.com/dropbox/dropbox-sdk-python/commit/1a3c241
TalkDropbox at CppCon2014-09

From the Dropbox Trenches (Kabbes, Grue)

Camera Uploads "shipped 4 months apart" by "~3 engineers"; without a bridge tool, one function meant code in "5 places"; GC pauses of 500 ms at 500k objects on a Nexus 4.

Carry forwardRecord the conditions that justified a seam, so you can tell when they lapse.
raw.githubusercontent.com/CppCon/CppCon2014/.../From the Dropbox Trenches.pdf
TalkDropbox at CppCon2014-09

Practical Cross-Platform Mobile C++ Development at Dropbox (Allain, Twyman)

The bridge is "Hard to get right" and "Filled with boilerplate"; "General: inconsistent debugging"; the goal stated as "zero cost for cross-platform dev".

Carry forwardA cost listed on the first slide deck does not go away because a generator exists.
raw.githubusercontent.com/CppCon/CppCon2014/.../Practical Cross-Platform.pdf
TalkDropbox at CppCon2015-09

Bridging Languages Cross-Platform (Twyman, Potter)

Djinni's principle: "Method calls pass control between languages. Not serialized RPC." One interface yields eight files of JNI and Objective-C++ glue.

Carry forwardIn-process seams trade serialisation cost for shared failure domains and toolchains.
raw.githubusercontent.com/CppCon/CppCon2015/.../Bridging Languages.pdf
SourceDropbox2019-04

djinni: Update README with maintenance status

"This repo is stable but no longer maintained by Dropbox", committed by one of the 2014 and 2015 speakers.

Carry forwardCommit share is the early signal; the notice arrives years later.
github.com/dropbox/djinni/commit/dfb9982
StandardPython2014-09

PEP 484: Type Hints

Co-authored by mypy's creator; "strongly inspired by mypy"; gradual typing so annotations can be added one function at a time.

Carry forwardPush an internal seam into a standard and its maintenance stops being yours.
raw.githubusercontent.com/python/peps/main/peps/pep-0484.rst
SourcePython / Dropbox2013-2026

python/mypy commit history

Dropbox-addressed commits peak at 321 (2015) and 297 (2016), then fall to zero in 2025 and 2026 while total yearly commits stay in the high hundreds.

Carry forwardA sponsor can leave a standardised tool without it dying.
github.com/python/mypy
SourcePython2019-04

mypyc README and mypy 0.700 on PyPI

mypy compiled by mypyc since 2019 for a claimed 4x; 0.700 is the first release with CPython-ABI wheels.

Carry forwardTypes written for safety became the input to a performance step.
raw.githubusercontent.com/mypyc/mypyc/.../README.md
Design docSQLAlchemy2024-07

Mypy / PEP-484 support for ORM mappings (deprecation)

The plugin "cannot be maintained across constantly changing releases of mypy"; replaced by native, PEP 484 compliant declarative typing in 2.0.

Carry forwardPlugins into another tool's internals are scaffolding with a cadence you do not set.
raw.githubusercontent.com/sqlalchemy/sqlalchemy/rel_2_0/.../mypy.rst
SourceDropbox2021-01

sqlalchemy-stubs on PyPI

Stubs plus a mypy plugin for SQLAlchemy's "magic"; last release 0.4 on 12 January 2021, last commit November 2022.

Carry forwardThird-party stubs end when the library types itself; plan for that.
pypi.org/project/sqlalchemy-stubs
SourceDropbox2019-09

pyannotate on PyPI

Infers annotations from runtime call arguments and return types; last release 1.2.0 on 16 September 2019.

Carry forwardMigration tooling that stops is often a migration that finished.
pypi.org/project/pyannotate
SourceDropbox2026-04

mypy-protobuf on PyPI and git

Schema-to-stubs generator; 46 releases, latest 5.1.0 in April 2026; zero Dropbox-addressed commits since 2022, maintained by its original author from a personal address.

Carry forwardGenerators keyed to a stable schema outlive their sponsor.
pypi.org/project/mypy-protobuf
SourceDropbox2026

pb-jelly README

Rust protobuf code generation written in 2016 for Magic Pocket to avoid double serialisation; now also in the sync engine.

Carry forwardChange language where the bytes are, and keep the schema the same.
raw.githubusercontent.com/dropbox/pb-jelly/.../README.md
SourceDropbox / community2026

rust-brotli on the crates.io index

Latest crate 9.0.0; 170 of 387 commits Dropbox-addressed in 2018, none of 153 in 2024.

Carry forwardA codec for a standard format finds maintainers; a private format does not.
index.crates.io/br/ot/brotli
SourceDropbox2023-08

dbx_build_tools README

Bazel rules for "hermetic Python binaries" with an interpreter built by Bazel; 326 of 330 commits in 2020 from Dropbox; last commit August 2023.

Carry forwardAn open-sourced build system nobody else commits to is an internal tool with a public mirror.
raw.githubusercontent.com/dropbox/dbx_build_tools/.../README.md
SourceDropbox2026-06

AffectedModuleDetector archive notice

Dropbox's Gradle plugin for testing only changed Android modules, archived and handed to Flo Health in June 2026.

Carry forwardNative-platform tooling is now where the mobile investment shows up, and it too gets handed on.
raw.githubusercontent.com/dropbox/AffectedModuleDetector/.../README.md
SourceDropbox2023-06

godropbox on the Go module proxy

Last pseudo-version 23 June 2023; 255 of 318 commits Dropbox-addressed in 2014; no deprecation notice in the README.

Carry forwardRead the registry's last-publish date, not the README's tense.
proxy.golang.org/github.com/dropbox/godropbox/@latest
07

Build a miniature, then audit your own seams

Six rungs, from a toy IDL to an audit of the clients you have already shipped. Each one reproduces a decision from this corpus.

Write a two-route spec and generate two clients

Install Stone from PyPI, describe one struct and two routes, and generate Python and JavaScript clients with its built-in backends.

Done when: both clients call a local stub server.  Teaches: the spec, not either client, is the artefact you version.

Break it on purpose, then don't

Apply each change in evolve_spec.rst's two lists to your spec and run an old generated client against a new server, and the reverse.

Done when: you have a table of which changes broke which direction.  Teaches: compatibility is sender and receiver, not version numbers.

Add a pinned CA file and rotate the server certificate

Ship the client with a bundled CA, then reissue the stub server's certificate from a new CA. Repeat with the platform trust store and an opt-in ca_certs.

Done when: the pinned client fails before any route runs and the other does not.  Teaches: the failure in section 04, in ten minutes.

Type a module gradually, with an end date for the scaffolding

Take an untyped Python module, collect runtime types with pyannotate under its tests, apply them, and get mypy clean. Write the date you will delete any stub or plugin you added.

Done when: mypy passes in strict mode for that module.  Teaches: migration tools are meant to stop.

Compile what you typed

Run mypyc on the typed module and benchmark it against the interpreted version.

Done when: you have your own speed-up figure to set against the claimed 4x.  Teaches: types as a performance input, not only a safety one.

Audit the clients you have already shipped

For every SDK or agent you distribute, list what it carries that your IDL does not describe: CA files, hostnames, TLS settings, retry constants, feature flags. Give each an owner and a rotation plan.

Done when: each item is in the contract, is fetched at runtime, or is deleted.  Teaches: the production version of rung 3.

08

Keep hunting

The commands and queries that produced this guide. The git ones work from any network that can clone GitHub.

Read a company from its repositories

  • git clone --filter=blob:none --no-checkout https://github.com/dropbox/djinni
  • git log --since=2015-01-01 --until=2015-12-31 --format=%ae | grep -ci dropbox
  • git show HEAD:README.md | grep -iE 'archiv|deprecat|no longer|maintenance'
  • git log --format='%ad %h %s' --date=short --grep='Automated Spec Update'

Find the incident trail in issues and READMEs

  • repo:dropbox/dropbox-sdk-java certificate pinning
  • repo:dropbox/dropbox-sdk-python certificate
  • "stopped working in January 2026" dropbox sdk
  • "no longer maintained by Dropbox"

Date things from the registries

  • curl -s https://pypi.org/pypi/mypy/json
  • curl -s https://proxy.golang.org/github.com/dropbox/godropbox/@latest
  • curl -s https://api.nuget.org/v3/registration5-semver1/dropbox.api/index.json
  • curl -s https://index.crates.io/br/ot/brotli

Talks hosted as slides, not video

  • git clone --depth 1 --filter=blob:none https://github.com/CppCon/CppCon2014
  • git ls-tree -r --name-only HEAD | grep -i dropbox
  • Djinni "not serialized RPC" CppCon 2015
  • site:dropbox.tech api-server-certificate-changes
09

The lesson: the contract is everything the client carries

Read across ten years, Dropbox's record makes one claim with unusual clarity. Language seams that crossed a network and were described by a schema lasted; the generators behind them (Stone, pb-jelly, mypy-protobuf) are still shipping in 2026, and mypy-protobuf is maintained by its original author from a personal address, four years after his last Dropbox-addressed commit. Seams that shared a process (Djinni) or shared a parser of hostile input (Lepton) were retired once the people who could debug both sides moved on. Scaffolding around a migration (pyannotate, sqlalchemy-stubs, the internal build mirror) stopped, mostly without saying so, which is what finished scaffolding should do.

And the one break that reached every unupgraded customer did not come from any of those. It came from a file that sat beside the generated code in the SDK's first commit, outside the schema's vocabulary, and therefore outside the compatibility rules Dropbox wrote and honoured. The design note was right that clients "may never be updated". It applied that insight to fields and routes and not to the trust anchor.

Carry this into your own design review

Your API contract is everything your client package carries, not only what your IDL can express. Put each language seam where a schema can describe what crosses it; when you must share a process, make sure the people on both sides can debug it; give every piece of migration scaffolding an end date; and before you ship a client you cannot force-upgrade, list every hand-written constant in it (certificates, hostnames, TLS and retry settings) and either move it into the versioned contract, fetch it at runtime, or delete it. The cost of skipping that list is paid years later by customers you cannot reach.

10

References

  1. Dropbox, dropbox-sdk-java issue #57, "Trust anchor for certification path not found" GitHub, June 2016. Checked 2026-10-15.
  2. Dropbox, dropbox-sdk-python issue #60, "out of date certificate file in SDK?" GitHub, April 2016. Checked 2026-10-15.
  3. Dropbox, dropbox-sdk-python README at 1a3c241 GitHub, 2026. Checked 2026-10-15.
  4. Dropbox, "Update README.rst with note about server certificate changes (#514)" GitHub, 2025-11-05. Checked 2026-10-15.
  5. Dropbox, dropbox-sdk-java README at 590eec4 GitHub, 2026. Checked 2026-10-15.
  6. Dropbox, dropbox-sdk-dotnet README at b0f0b18 GitHub, 2026. Checked 2026-10-15.
  7. NuGet registration index, Dropbox.Api Published 2024-05-22. Checked 2026-10-15.
  8. Dropbox, dropbox-sdk-python PR #489, "Stop providing a hardcoded CA bundle" GitHub, 2024-05-09. Checked 2026-10-15.
  9. Dropbox, dropbox-sdk-java PR #537, "Remove cert pinning from the SDK" GitHub, 2024-04-29. Checked 2026-10-15.
  10. Dropbox, dropbox-sdk-python initial commit f72f99d GitHub, 2015-06-15. Checked 2026-10-15.
  11. Dropbox, dropbox-sdk-python commit 41e4b00, removing the CA bundle GitHub, 2024-05-09. Checked 2026-10-15.
  12. PyPI, dropbox 12.0.2 Uploaded 2024-06-03. Checked 2026-10-15.
  13. Dropbox, Stone, "Evolving a Spec" GitHub, added 2017-03-02. Checked 2026-10-15.
  14. Dropbox, Stone initial commit 93373c4 GitHub, 2014-07-21. Checked 2026-10-15.
  15. PyPI, stone 27 releases, 2016-06-03 to 2026-09-23. Checked 2026-10-15.
  16. Dropbox, dropbox-api-spec commit 3c363a5, "Update API specification (#138)" GitHub, 2026-10-09. Checked 2026-10-15.
  17. Dropbox, dropbox-sdk-python "Automated Spec Update (#613)" GitHub, 2026-10-09. Checked 2026-10-15.
  18. npm registry, dropbox 155 versions, modified 2026-09-23. Checked 2026-10-15.
  19. Maven Central, dropbox-core-sdk metadata Latest 8.0.2, updated 2026-07-15. Checked 2026-10-15.
  20. Steven Kabbes and Tony Grue, "From the Dropbox Trenches" CppCon 2014 slides, CppCon GitHub. Checked 2026-10-15.
  21. Alex Allain and Andrew Twyman, "Practical Cross-Platform Mobile C++ Development at Dropbox" CppCon 2014 slides. Checked 2026-10-15.
  22. Andrew Twyman and Jacob Potter, "Bridging Languages Cross-Platform" CppCon 2015 slides. Checked 2026-10-15.
  23. Dropbox, djinni commit dfb9982, maintenance status GitHub, 2019-04-11. Checked 2026-10-15.
  24. Dropbox, djinni repository GitHub, 2014 to 2020. Checked 2026-10-15.
  25. Dropbox, lepton issue #158, "Lepton denial-of-service with specially crafted JPEG files" GitHub, 2022-11-18. Checked 2026-10-15.
  26. Dropbox, lepton README and deprecation notice GitHub, 2023-02-13. Checked 2026-10-15.
  27. Microsoft, lepton_jpeg_rust GitHub. Checked 2026-10-15.
  28. Dropbox, pb-jelly README GitHub. Checked 2026-10-15.
  29. crates.io index, brotli Latest 9.0.0. Checked 2026-10-15.
  30. Guido van Rossum, Jukka Lehtosalo and Łukasz Langa, PEP 484, "Type Hints" Python, created 2014-09-29. Checked 2026-10-15.
  31. python/mypy repository GitHub, 2012 to 2026. Checked 2026-10-15.
  32. mypyc README GitHub, 2021-03-07. Checked 2026-10-15.
  33. PyPI, mypy 0.700 Uploaded 2019-04-03. Checked 2026-10-15.
  34. SQLAlchemy, "Mypy / Pep-484 Support for ORM Mappings" SQLAlchemy 2.0 docs source, updated July 2024. Checked 2026-10-15.
  35. PyPI, sqlalchemy-stubs Last release 2021-01-12. Checked 2026-10-15.
  36. PyPI, pyannotate Last release 2019-09-16. Checked 2026-10-15.
  37. PyPI, mypy-protobuf Latest 5.1.0, 2026-04-28. Checked 2026-10-15.
  38. Dropbox, dbx_build_tools README GitHub, last commit 2023-08-16. Checked 2026-10-15.
  39. Dropbox, AffectedModuleDetector README with archive notice GitHub, 2026-06-16. Checked 2026-10-15.
  40. Go module proxy, github.com/dropbox/godropbox latest 2023-06-23. Checked 2026-10-15.