A settembre dello scorso anno, abbiamo lanciato un importante aggiornamento di Proton Mail per iOS e Android.

In superficie, le nuove app offrono un design moderno, migliori prestazioni e funzionalità offline—ma c’è molto più di quanto sembri. Dietro le quinte, le app sono una riscrittura completa di Proton Mail su uno stack tecnologico innovativo, un progetto che porta il nome interno di Engineering Transformation. Il termine innovativo è deliberato, perché — per quanto ne sappiamo — è stata la prima volta che la tecnologia scelta è stata utilizzata nel contesto di un’applicazione di produzione consolidata.

Questo articolo mira a far luce sull’affascinante viaggio che il nostro team ha attraversato nella realizzazione di questa rivoluzione e a rispondere ad alcune delle domande che la nostra comunità ci ha posto lungo il percorso. Innanzitutto, la logica alla base è la necessità di cambiare lo status quo.

Com’è iniziato tutto

La consapevolezza che le cose dovessero cambiare è arrivata un venerdì sera di ottobre 2023. Si è materializzata con sorprendente chiarezza, ma non dal nulla: è stato il culmine di mesi passati a cercare di trovare un denominatore comune per i problemi apparentemente non correlati che influenzavano l’esperienza dei nostri utenti con i prodotti mobili Mail e Calendar.

A rischio di semplificare eccessivamente, possiamo riassumere i punti dolenti in tre aree:

  • Qualità: Mail iOS e Mail Android, prese singolarmente, non hanno soddisfatto le aspettative in termini di qualità e prestazioni.
  • Divario di funzionalità tra iOS e Android: alcune funzionalità erano disponibili solo su una piattaforma, senza chiarezza su quando l’altra si sarebbe adeguata.
  • Velocità ingegneristica: aggiornamenti chiave e funzionalità tanto attese non venivano rilasciati in modo tempestivo su entrambe le piattaforme.

Alcuni dei problemi si estendevano oltre il mobile e risponderci richiederebbe una digressione dal dominio tecnologico all’affascinante spazio dei problemi di scalabilità organizzativa, e in particolare delle startup tecnologiche in rapida crescita. Ma la fragilità dell’ecosistema mobile era molto radicata nella tecnologia e nell’architettura.

Scalare l’ingegneria mobile

Scalare l’ingegneria mobile comporta una serie unica di sfide che sono significativamente diverse dallo scalare team backend e web. Queste differenze derivano dalla frammentazione della piattaforma e dalle realtà operative dell’ecosistema mobile. I team mobili in genere devono supportare più piattaforme su una varietà di sistemi operativi e dispositivi (telefoni, tablet, a volte indossabili). iOS e Android hanno i propri linguaggi di programmazione, framework e strumenti, il che porta a grandi quantità di sforzi duplicati: più team, codebase duplicate e costanti compromessi tra lavoro specifico della piattaforma e legato al prodotto. Mantenere l’offerta di prodotti sincronizzata richiede un’enorme quantità di coordinamento.

Quella che è una sfida a livello di settore era particolarmente acuta per Proton. Le app di funzionalità come Mail e Calendar sono intrinsecamente più complesse della maggior parte delle applicazioni mobili sul mercato. Quando aggiungi sopra l’ulteriore livello di logica client richiesto per gestire la crittografia end-to-end, finisci con client particolarmente “pesanti”. All’epoca, il team Android era impegnato a riscrivere Mail per migliori standard di qualità—un investimento che ha richiesto la maggior parte di 18 mesi. Anche iOS aveva un disperato bisogno di riarchitettura, per non parlare di Calendar. Il costo della duplicazione stava consumando tutte le nostre risorse ingegneristiche ed è diventato chiaro che non avremmo avuto successo facendo più dello stesso.

La cosa migliore del riconoscere di essere bloccati è che agisce come un fattore di forzatura per pensare fuori dai vincoli del tuo attuale status quo. Cosa faremmo se potessimo ricominciare da capo, liberi dal peso delle scelte e degli impegni che ci hanno portato qui? Quando guardi più da vicino come le aziende di successo hanno affrontato questo problema nel decennio precedente, ti rendi conto che hanno seguito una di due sole strategie possibili:

  1. Hanno gettato soldi sul problema, costruendo team sempre più grandi poiché gli alti costi operativi erano compensati da una combinazione di investimenti senza fondo e/o profitti sontuosi. Questa non era un’opzione per il modello di business senza VC di Proton: non possiamo competere con la spesa dei concorrenti basati su annunci e sostenuti da investitori.
  2. Hanno reingegnerizzato le loro app per sbarazzarsi degli sprechi, il che significa costruire app utilizzando (il più possibile) una codebase condivisa.

Con l’opzione 1 esclusa in partenza, la strada da percorrere era tracciata.

Un mezzo per un fine: scegliere lo stack tecnologico giusto

Il passaggio successivo è stato scegliere uno stack tecnologico che potesse effettivamente svolgere il lavoro.

Negli ultimi 15 anni, lo sviluppo mobile multipiattaforma è stato inondato di soluzioni “taglia unica”: HTML5, Xamarin, React Native, Flutter, Kotlin Multiplatform e molte altre. Ognuna è arrivata con la stessa promessa: sostituire del tutto lo sviluppo nativo. In pratica, la maggior parte ha fallito completamente o ha avuto successo solo in spazi problematica strettamente vincolati. Non esiste un’astrazione universale che faccia scomparire le differenze di piattaforma: chiunque abbia rilasciato e mantenuto grandi applicazioni mobili lo sa. L’unico modo affidabile per procedere è lavorare a ritroso dai requisiti concreti piuttosto che in avanti dalle tendenze degli strumenti.

Abbiamo tradotto quell’obiettivo finale in una serie di requisiti non negoziabili (1) che qualsiasi soluzione scelta doveva soddisfare e li abbiamo usati come nostro quadro guida durante tutto il processo di valutazione:

  1. Costi e tempistiche: lo stack doveva ridurre materialmente i costi e i tempi necessari per rilasciare, mantenere ed evolvere Proton Mail su iOS e Android.
  2. Esperienza utente: doveva preservare prestazioni e qualità di interazione quasi native: qualsiasi cosa di meno era inaccettabile.
  3. Strategia a prova di futuro: la soluzione doveva essere longeva. Eravamo intenzionati a evitare framework di terze parti che avrebbero reso la nostra roadmap dipendente dal supporto continuo di un altro fornitore.

La tensione tra i primi due vincoli è la versione del settore del Santo Graal: “Una soluzione multipiattaforma che offre le prestazioni e l’esperienza utente delle applicazioni native.”

Eravamo scettici fin dall’inizio che React Native o Flutter — i due framework multipiattaforma dominanti all’epoca — potessero soddisfare questo standard. Tuttavia, abbiamo convalidato quello scetticismo costruendo implementazioni proof-of-concept della visualizzazione elenco messaggi di Mail.

React Native ha rivelato rapidamente i suoi limiti. Scorrere un set di dati di grandi dimensioni rendeva dolorosamente ovvio il costo del suo modello di esecuzione interpretato. Flutter si comportava meglio, ma l’interfaccia utente rimaneva visibilmente non nativa, specialmente su iOS. Ancora più importante, Flutter è un framework proprietario controllato da Google, che ha una storia(nuova finestra) di abbandono delle tecnologie interne e aveva recentemente licenziato gran parte del team Flutter. Per un prodotto con garanzie di sicurezza e affidabilità a lungo termine, quel livello di dipendenza esterna era inaccettabile.

Kotlin Multiplatform è stato il candidato successivo. È un’opzione avvincente — in particolare per le organizzazioni con profonda esperienza Android — ma alla fine non è stata all’altezza del nostro caso d’uso. L’assenza di un livello UI condiviso, le domande sulla maturità e l’overhead aggiuntivo introdotto dal suo modello di esecuzione hanno superato i suoi benefici.

A questo punto, la conclusione era chiara e allineata con la nostra intuizione iniziale: l’unica architettura che si avvicina costantemente al risultato desiderato è uno stack deliberatamente misto. UI nativa su ogni piattaforma – Jetpack Compose su Android, SwiftUI su iOS – supportata da un livello di logica aziendale condiviso scritto in un linguaggio di basso livello ad alte prestazioni. Questo approccio ha dei precedenti: Dropbox ha notoriamente usato C++ per condividere la logica aziendale tra piattaforme mobili prima di abbandarlo nel 2019 a causa del costo operativo e cognitivo del linguaggio.

Entro la fine del 2023, Rust era chiaramente emerso come successore nella linea dei linguaggi di programmazione di sistema.

Rust occupa la stessa fascia di prestazioni del C++, ma senza molte delle sue passività storiche. Fornisce forti garanzie di sicurezza della memoria senza garbage collection, impone la concorrenza thread-safe in fase di compilazione ed è supportato da un ampio ecosistema open source altamente competente. Altrettanto importante, Rust si integra in modo pulito con i linguaggi mobili nativi — Swift e SwiftUI su iOS, Kotlin e Jetpack Compose su Android — rendendolo una scelta pragmatica per condividere la logica principale senza compromettere il livello UI.

Non è stata una decisione priva di rischi. All’epoca, c’erano pochi esempi di applicazioni mobili consumer su larga scala costruite su un’architettura incentrata su Rust e l’esperienza Rust all’interno del team era limitata.

Ma l’innovazione significativa accade raramente in territorio a basso rischio. La vera sfida non era Rust in sé, ma l’inerzia organizzativa: passare da approcci collaudati e conservatori a una sperimentazione deliberata, guidata da chiari vincoli e giudizio ingegneristico.

La nuova Proton Mail: risultati e insegnamenti

Facciamo un salto in avanti a oggi e vediamo come è andata la scommessa.

Il diagramma seguente rappresenta l’architettura mobile di Mail. Il core Rust è responsabile dell’intera logica aziendale dell’applicazione. Abbiamo spinto l’uso di Rust oltre le sue solite applicazioni (networking, archiviazione, calcolo algoritmico) fino alla gestione della complessa logica di navigazione. Un esempio calzante è la logica che governa lo scorrimento infinito dell’elenco dei messaggi. Sebbene non ortodosso, questo si è rivelato fondamentale per raggiungere il nostro obiettivo di massimizzare il riutilizzo del codice. Di conseguenza, quasi l’80% della codebase è ora condiviso tra iOS e Android.

Diagramma architettonico per gentile concessione di Leander Beernaert, 2026
Diagramma architettonico per gentile concessione di Leander Beernaert, 2026

Questo si è tradotto in un time-to-market più rapido e di qualità superiore? Sebbene sia ancora troppo presto per un verdetto finale, i primi segnali sono stati molto incoraggianti:

  • Nei due mesi successivi al rilascio, il team è riuscito a mantenere una cadenza settimanale di aggiornamenti delle funzionalità su entrambe le piattaforme (un totale di 12 rilasci di funzionalità).
  • Abbiamo colmato i divari di funzionalità tra le piattaforme, portando su Android funzionalità tanto attese come posponi, RSVP del calendario e swipe per il messaggio successivo.
  • Anche in questa fase iniziale, la nuova codebase si è dimostrata più stabile delle generazioni precedenti su entrambe le piattaforme: il tasso di crash su iOS è dello 0,05% (in calo dallo 0,12%), mentre quello di Android è tornato a un livello storico (0,19%). Questo è un forte sostegno alla stabilità di runtime di Rust.

Anche il supporto scala in modo più efficace con questo approccio. Spesso è più veloce identificare e risolvere una singola causa principale condivisa piuttosto che inseguire problemi superficialmente simili derivanti da difetti logici leggermente diversi sparsi su due codebase indipendenti. Abbiamo trovato conferma empirica di quella che era stata in precedenza un’ipotesi di lavoro mentre sistemavamo una classe di problemi di sincronizzazione delle categorie che interessavano la logica alla base delle capacità offline dell’app: una causa principale, una soluzione — rappresentata nel diagramma sopra dal modulo Rebasing rilasciato con la versione 7.6.2.

L’altra faccia della medaglia?

  • È probabile che bug e regressioni abbiano un impatto più ampio e colpiscano gli utenti su entrambe le piattaforme. Non puoi avere tutto, ma puoi sicuramente mitigare il rischio puntando molto sui test end-to-end (E2E).
  • Come per qualsiasi suddivisione di una soluzione rivolta all’utente lungo una divisione tecnologica orizzontale, c’è il rischio di creare silos di conoscenza e perdere un po’ di attenzione ingegneristica sulle esperienze utente end-to-end. Devi esserne consapevole e mitigare intenzionalmente il rischio. Tra le misure più efficaci:
    • Allinea i sottoteam per fornire funzionalità piuttosto che livelli tecnologici.
    • Forma gli ingegneri mobili per diventare “full stack”, ovvero in grado di eseguire il debug, supportare e ingegnerizzare sia la codebase Rust che le piattaforme native.

Cosa c’è dopo per Engineering Transformation

Fin dall’inizio di questo progetto, era chiaro che la posta in gioco si estendeva ben oltre la sola Proton Mail. Applicare con successo questo stack tecnologico all’applicazione di punta di Proton è sempre stato inteso come il primo passo di un viaggio più lungo, che avrebbe visto in definitiva questo approccio esteso al resto del nostro ecosistema mobile.

Quello scenario si sta ora svolgendo. Mentre scrivo questo articolo, i nostri SDK Account e Payment, così come la prossima generazione di app mobili Proton Calendar, vengono riscritti in linea con questa nuova direzione tecnica.

Questo segna l’inizio di una seconda ondata di trasformazione ingegneristica — un’evoluzione che espande il progetto tecnologico con un framework architettonico progettato per rendere il riutilizzo dei componenti più facile, non solo tra piattaforme ma anche tra prodotti. Sebbene questa transizione non avverrà dall’oggi al domani, è fondamentale per costruire l’ecosistema perfettamente integrato e orientato alla privacy che i nostri clienti si aspettano che Proton sia.

(1): Simon Lewis, “A strategy for application implementation on multiple platforms”, 2023.