SQLite vs Realm per l'archiviazione offline-first nelle app da campo
Confronto SQLite vs Realm per archiviazione offline-first in app da campo: migrazioni, opzioni di query, gestione dei conflitti, strumenti di debug e consigli pratici per la scelta.

Di cosa hanno davvero bisogno le app da campo offline-first
Offline-first non significa solo “funziona senza internet”. Significa che l'app può caricare dati utili, accettare nuovi input e mantenere ogni modifica al sicuro fino a quando può sincronizzarsi.
Il lavoro sul campo aggiunge vincoli prevedibili: il segnale salta, le sessioni sono lunghe, i dispositivi possono essere vecchi e le modalità di risparmio energetico sono comuni. Le persone vanno veloci. Aprono un lavoro, scorrono lunghi elenchi, scattano foto, compilano moduli e passano al compito successivo senza pensare allo storage.
Quello che gli utenti notano è semplice. Perdono fiducia quando le modifiche spariscono, quando gli elenchi e la ricerca vanno a rilento offline, quando l'app non risponde chiaramente a “il mio lavoro è salvato?”, quando i record si duplicano o scompaiono dopo la riconnessione, o quando un aggiornamento causa comportamenti strani.
Per questo scegliere tra SQLite e Realm riguarda soprattutto il comportamento quotidiano, non i benchmark.
Prima di scegliere un database locale, chiarisci quattro aspetti: il tuo modello dati cambierà, le tue query devono rispecchiare i flussi reali, la sincronizzazione offline genererà conflitti e gli strumenti decideranno quanto velocemente puoi diagnosticare i problemi sul campo.
1) I tuoi dati cambieranno
Anche le app stabili evolvono: nuovi campi, stati rinominati, nuove schermate. Se le migrazioni sono dolorose, o rilasci meno miglioramenti o rischi di rompere dispositivi reali con dati reali.
2) Le query devono rispecchiare i flussi reali
Le app da campo hanno bisogno di filtri veloci come “lavori di oggi”, “siti vicini”, “moduli non sincronizzati” e “elementi modificati nelle ultime 2 ore”. Se il database rende queste query macchinose, l'interfaccia rallenta o il codice diventa un labirinto.
3) La sincronizzazione offline crea conflitti
Due persone possono modificare lo stesso record, o un dispositivo può lavorare su dati vecchi per giorni. Serve un piano chiaro su cosa vince, cosa si fonde e cosa richiede una decisione umana.
4) Gli strumenti contano
Quando qualcosa va storto sul campo, devi ispezionare i dati, riprodurre i problemi e capire cosa è successo senza supposizioni.
Migrazioni: cambiare il modello dati senza rompere gli utenti
Le app da campo raramente restano ferme. Dopo poche settimane aggiungi una checkbox, rinomini uno stato o dividi il campo “note” in campi strutturati. Le migrazioni sono dove le app offline spesso falliscono, perché il telefono contiene già dati reali.
SQLite memorizza i dati in tabelle e colonne. Realm memorizza i dati come oggetti con proprietà. La differenza si vede subito:
- Con SQLite normalmente scrivi cambi di schema espliciti (ALTER TABLE, nuove tabelle, copia dei dati).
- Con Realm in genere aumenti la versione dello schema ed esegui una funzione di migrazione che aggiorna gli oggetti quando vengono acceduti.
Aggiungere un campo è facile in entrambi: aggiungi una colonna in SQLite, una proprietà con default in Realm. Rinominare e dividere sono i casi dolorosi. In SQLite la rinomina può essere limitata a seconda della configurazione, quindi i team spesso creano una nuova tabella e copiano i dati. In Realm puoi leggere la vecchia proprietà e scrivere nelle nuove durante la migrazione, ma bisogna fare attenzione a tipi, valori di default e null.
Aggiornamenti massivi con dati sul dispositivo richiedono cautela. Una migrazione che riscrive ogni record può essere lenta su telefoni vecchi, e un tecnico non dovrebbe restare bloccato a guardare una rotella di caricamento in un parcheggio. Pianifica il tempo di migrazione e considera di distribuire trasformazioni pesanti su più release.
Per testare le migrazioni in modo corretto trattale come la sincronizzazione:
- Installa una build vecchia, crea dati realistici, poi aggiorna.
- Testa con dataset piccoli e grandi.
- Uccidi l'app a metà migrazione e riavviala.
- Testa scenari di spazio di archiviazione basso.
- Parti dal presupposto che puoi andare avanti con la migrazione anche se non puoi tornare indietro.
Esempio: se “equipmentId” diventa “assetId” e poi si divide in “assetType” e “assetNumber”, la migrazione dovrebbe mantenere utilizzabili le vecchie ispezioni, non forzare logout o cancellazioni.
Flessibilità delle query: cosa puoi chiedere ai tuoi dati
Le app da campo vivono e muoiono sulle schermate elenco: i lavori di oggi, asset vicini, clienti con ticket aperti, parti usate questa settimana. La scelta dello storage dovrebbe rendere queste domande facili da esprimere, veloci da eseguire e difficili da fraintendere tra sei mesi.
SQLite ti dà SQL, che resta il modo più flessibile per filtrare e ordinare grandi dataset. Puoi combinare condizioni, fare join tra tabelle, raggruppare risultati e aggiungere indici quando una schermata rallenta. Se l'app richiede “tutte le ispezioni per asset nella Regione A, assegnate al Team 3, con qualsiasi voce della checklist fallita”, SQL di solito lo esprime in modo pulito.
Realm punta su oggetti e su un'API di query di livello più alto. Per molte app questo è naturale: interroga oggetti Job, filtra per stato, ordina per data di scadenza, segui le relazioni con oggetti correlati. Lo scambio è che alcune domande banali in SQL (soprattutto query in stile report su più relazioni) possono essere più difficili da esprimere, o finisci per rimodellare i dati per adattarli alle query necessarie.
Ricerca e relazioni
Per la ricerca testuale parziale su più campi (titolo lavoro, nome cliente, indirizzo), SQLite spesso ti spinge verso un indicizzazione attenta o un approccio full-text dedicato. Realm può filtrare testo, ma devi comunque pensare a prestazioni e a cosa significa “contains” su larga scala.
Le relazioni sono un altro punto pratico. SQLite gestisce one-to-many e many-to-many con tabelle di join, il che rende semplici pattern come “asset taggati con questi due tag”. I link di Realm sono facili da navigare in codice, ma molti-a-molti e query “attraverso” richiedono più pianificazione per mantenere le letture veloci.
Query raw vs manutenzione leggibile
Un pattern che aiuta la manutenzione è mantenere un piccolo set di query nominate che mappano direttamente alle schermate e ai report: i filtri principali per le liste, la query di dettaglio (un record più i record correlati), la definizione di ricerca, qualche contatore (badge e totali offline) e le query di esportazione/report.
Se ti aspetti domande ad hoc frequenti dal business, la potenza delle query raw di SQLite è difficile da battere. Se vuoi che la maggior parte degli accessi ai dati si legga come lavoro con oggetti normali, Realm può sembrare più rapido da costruire, purché risponda alle tue schermate più complesse senza stratagemmi scomodi.
Risoluzione dei conflitti e sincronizzazione: quale supporto ottieni
Le app offline-first di campo normalmente supportano le stesse azioni core da disconnesse: creare un record, aggiornare un record, cancellare qualcosa non valido. La parte difficile non è salvare localmente. È decidere cosa succede quando due dispositivi cambiano lo stesso record prima che uno dei due abbia sincronizzato.
I conflitti emergono in situazioni semplici. Un tecnico aggiorna un'ispezione su un tablet in un seminterrato senza segnale. Più tardi, un supervisore corregge la stessa ispezione da un laptop. Quando entrambi si riconnettono, il server riceve due versioni diverse.
La maggior parte dei team adotta uno di questi approcci:
- Last write wins (veloce, ma può sovrascrivere dati validi in modo silenzioso)
- Merge per campo (più sicuro quando cambiano campi diversi, ma richiede regole chiare)
- Revisione manuale (più lento, migliore per cambi ad alto rischio)
SQLite ti dà un database locale affidabile, ma non fornisce la sincronizzazione di per sé. Di solito costruisci il resto: traccia operazioni in sospeso, inviale a un'API, riprova in modo sicuro e fai rispettare le regole di conflitto sul server.
Realm può ridurre la quantità di plumbing se usi le sue funzionalità di sync, perché è progettato attorno agli oggetti e al tracciamento delle modifiche. Ma la “sync integrata” non sceglie comunque le tue regole di business. Sei tu a decidere cosa conta come conflitto e quali dati possono vincere.
Pianifica una traccia di audit fin da subito. Le squadre sul campo spesso hanno bisogno di risposte chiare a “chi ha cambiato cosa, quando e da quale dispositivo”. Anche se scegli last write wins, memorizza metadati come user ID, device ID, timestamp e (quando possibile) una motivazione. Se il tuo backend è generato rapidamente, per esempio con una piattaforma no-code come AppMaster, è più facile iterare su queste regole presto prima di avere centinaia di dispositivi offline in produzione.
Debug e ispezione: catturare i problemi prima che li noti il campo
I bug offline sono difficili perché accadono quando non puoi vedere l'app parlare con un server. La tua esperienza di debug spesso si riduce a una domanda: quanto è facile vedere cosa c'è sul dispositivo e come è cambiato nel tempo?
SQLite è facile da ispezionare perché è un file. In sviluppo o QA puoi estrarre il database da un dispositivo di test, aprirlo con strumenti SQLite comuni, eseguire query ad hoc ed esportare tabelle in CSV o JSON. Questo ti aiuta a confermare “quali righe esistono” rispetto a “cosa mostra l'interfaccia”. Lo svantaggio è che devi capire il tuo schema, i join e qualsiasi scaffolding di migrazione che hai creato.
Realm può sembrare più “app-like” da ispezionare. I dati sono memorizzati come oggetti e gli strumenti di Realm sono spesso il modo più semplice per esplorare classi, proprietà e relazioni. È ottimo per individuare problemi nel grafo di oggetti (link mancanti, null inaspettati), ma l'analisi ad hoc è meno flessibile se il tuo team è abituato all'ispezione basata su SQL.
Logging e riproduzione dei problemi offline
La maggior parte dei fallimenti sul campo dipende da errori di scrittura silenziosi, batch di sincronizzazione parziali o una migrazione che si è fermata a metà. In ogni caso, investi in alcune cose basi: timestamp “last changed” per record, un log delle operazioni lato dispositivo, log strutturati intorno a migrazioni e scritture in background, la possibilità di abilitare logging verbose nelle build QA e un’azione “dump and share” che esporta uno snapshot redatto.
Esempio: un tecnico segnala che ispezioni completate spariscono dopo uno scaricamento della batteria. Uno snapshot condiviso ti aiuta a confermare se i record non sono mai stati scritti, sono stati scritti ma non interrogati, o sono stati annullati all'avvio.
Condividere uno snapshot fallito
Con SQLite, condividere è spesso semplice come inviare il file .db (più eventuali file WAL). Con Realm, di solito condividi il file Realm insieme ai file accessori. In entrambi i casi definisci un processo ripetibile per rimuovere dati sensibili prima che qualcosa esca dal dispositivo.
Affidabilità nel mondo reale: guasti, reset e aggiornamenti
Le app da campo falliscono in modi banali: la batteria muore durante un salvataggio, il SO uccide l'app in background o lo storage si riempie dopo settimane di foto e log. La scelta del database locale influisce su quante volte questi guasti si traducono in lavoro perso.
Quando un crash avviene a metà scrittura, sia SQLite che Realm possono essere sicuri se usati correttamente. SQLite è affidabile quando racchiudi le modifiche in transazioni (la modalità WAL aiuta resilienza e prestazioni). Le scritture in Realm sono transazionali per default, quindi di solito ottieni salvataggi “tutto o niente” senza lavoro extra. Il rischio comune non è il motore di database, ma il codice dell'app che scrive in più passaggi senza un chiaro punto di commit.
La corruzione è rara, ma serve un piano di recupero. Con SQLite puoi eseguire controlli di integrità, ripristinare da backup noti o ricostruire da una risincronizzazione con il server. Con Realm, la corruzione spesso rende sospetto l'intero file Realm, quindi il percorso pratico è spesso “elimina il locale e risincronizza” (accettabile se il server è la fonte di verità, doloroso se il dispositivo contiene dati unici).
La crescita dello storage è un'altra sorpresa. SQLite può gonfiarsi dopo le cancellazioni a meno che tu non esegua VACUUM periodici. Realm può crescere e potrebbe avere bisogno di politiche di compattazione, oltre al pruning di oggetti vecchi (come lavori completati) così il file non cresce all'infinito.
Aggiornamenti e rollback sono un'altra trappola. Se un aggiornamento cambia schema o formato di storage, un rollback può lasciare utenti su un file più nuovo che non si può leggere. Pianifica gli aggiornamenti come unidirezionali, con migrazioni sicure e un'opzione “reset dati locali” che non rompa l'app.
Abitudini di affidabilità che pagano:
- Gestisci “disco pieno” e errori di scrittura con un messaggio chiaro e una via di riprova.
- Salva l'input dell'utente in checkpoint intermedi, non solo alla fine di un modulo lungo.
- Mantieni un log di audit locale leggero per recupero e supporto.
- Sfoltisci e archivia record vecchi prima che il database diventi troppo grande.
- Testa aggiornamenti OS e kill in background su dispositivi economici.
Esempio: un'app di ispezione che conserva checklist e foto può raggiungere spazio basso in un mese. Se l'app rileva spazio insufficiente in anticipo, può sospendere la cattura di foto, caricare quando possibile e mantenere salvi i salvataggi delle checklist, indipendentemente dal database locale scelto.
Passo dopo passo: come scegliere e configurare l'archiviazione
Tratta lo storage come parte del prodotto, non come una decisione di libreria. L'opzione migliore è quella che mantiene l'app utilizzabile quando il segnale cade e prevedibile quando ritorna.
Un semplice percorso decisionale
Scrivi prima i tuoi flussi offline utente. Sii specifico: “apri i lavori di oggi, aggiungi note, allega foto, marca come completato, acquisisci una firma”. Tutto in quella lista deve funzionare senza rete, ogni volta.
Poi segui una breve sequenza: elenca le schermate critiche offline e quanta dati richiedono (i lavori di oggi vs tutta la cronologia), abbozza un modello dati minimo e le relazioni che non puoi simulare (Job -> ChecklistItems -> Answers), scegli una regola di conflitto per entità (non una sola regola per tutto), decidi come testerai i fallimenti (migrazioni su dispositivi reali, retry di sync, comportamento dopo logout/reinstall), e costruisci un piccolo prototipo con dati realistici che puoi cronometrare (caricamento, ricerca, salvataggio, sincronizzazione dopo un giorno offline).
Quel processo di solito rivela il vincolo reale: hai bisogno di query ad hoc flessibili e ispezione facile, o preferisci accesso basato su oggetti e vincoli di modello più rigidi?
Cosa validare nel prototipo
Usa uno scenario realistico, come un tecnico che completa 30 ispezioni offline e poi torna in copertura. Misura il primo caricamento con 5.000 record, se un cambiamento di schema sopravvive a un aggiornamento, quanti conflitti appaiono dopo la riconnessione e se sai spiegare ognuno, e quanto rapidamente puoi ispezionare un “record problematico” quando il supporto chiama.
Se vuoi validare rapidamente prima di impegnarti, un prototipo no-code in AppMaster può aiutarti a fissare flusso e modello dati presto, anche prima di finalizzare la scelta del database su dispositivo.
Errori comuni che danneggiano le app offline-first
La maggior parte dei fallimenti non deriva dal motore di database ma dal saltare le parti noiose: aggiornamenti, regole di conflitto e gestione chiara degli errori.
Una trappola è presumere che i conflitti siano rari. Nel lavoro sul campo sono normali: due tecnici modificano lo stesso asset o un supervisore cambia una checklist mentre un dispositivo è offline. Se non definisci una regola (last write wins, merge per campo o mantenere entrambe le versioni), prima o poi sovrascriverai lavoro reale.
Un altro fallimento silenzioso è trattare il modello dati come “definitivo” e non esercitarsi sugli aggiornamenti. Gli schemi cambiano anche in app piccole. Se non versioni il tuo schema e non testi gli aggiornamenti da build più vecchie, gli utenti possono restare bloccati dopo un update con migrazioni fallite o schermate vuote.
I problemi di prestazioni emergono tardi. I team a volte scaricano tutto “per sicurezza” e poi si chiedono perché la ricerca è lenta e l'app impiega minuti per aprirsi su uno smartphone di fascia media.
Pattern da tenere d'occhio:
- Nessuna policy scritta sui conflitti, così le modifiche vengono sovrascritte in modo silenzioso.
- Migrazioni che funzionano su installazioni pulite ma falliscono sugli aggiornamenti reali.
- Caching offline che cresce senza limiti, rendendo le query lente.
- Fallimenti di sync nascosti dietro una rotella, così gli utenti pensano che i dati siano stati inviati.
- Debugging per tentativi invece che con uno script di riproduzione ripetibile e dati di esempio.
Esempio: un tecnico completa un'ispezione offline, tocca Sync e non riceve conferma. L'upload è fallito per un problema di token di autenticazione. Se l'app nasconde l'errore, il tecnico lascia il sito pensando che il lavoro sia stato fatto e la fiducia viene meno.
Qualunque storage tu scelga, esegui un test base in “modalità campo”: modalità aereo, batteria bassa, aggiornamento app e due dispositivi che modificano lo stesso record. Se costruisci in fretta con una piattaforma no-code come AppMaster, integra questi test nel prototipo prima che il flusso raggiunga un team più grande.
Checklist rapida prima di impegnarti
Prima di scegliere un motore di storage, definisci cosa significa “buono” per la tua app da campo e testalo con dati reali e dispositivi reali. I team discutono sulle funzionalità, ma la maggior parte dei fallimenti deriva dalle basi: aggiornamenti, schermate lente, regole di conflitto poco chiare e impossibilità di ispezionare lo stato locale.
Usa questo come gate go/no-go:
- Dimostra gli aggiornamenti: prendi almeno due build più vecchie, aggiorna all'ultima e conferma che i dati continuano ad aprirsi, essere modificati e sincronizzati.
- Mantieni veloci le schermate core a volumi realistici: carica dati realistici e cronometra le schermate più lente su uno smartphone di fascia media.
- Scrivi una policy di conflitto per tipo di record: ispezioni, firme, parti usate, commenti.
- Rendi i dati locali ispezionabili e i log raccolgibili: definisci come support e QA catturano lo stato offline.
- Rendi il recupero prevedibile: decidi quando ricostruire la cache, riscaricare o richiedere nuovamente l'accesso. Non fare della “reinstallazione dell'app” il piano.
Se stai prototipando in AppMaster, applica la stessa disciplina. Testa aggiornamenti, definisci conflitti e prova il recupero prima di distribuirlo a un team che non può permettersi downtime.
Scenario di esempio: un'app di ispezione con segnale intermittente
Un tecnico inizia la giornata scaricando 50 ordini di lavoro sul telefono. Ogni lavoro include indirizzo, checklist richieste e alcune foto di riferimento. Dopo, il segnale salta durante la giornata.
Durante ogni intervento il tecnico modifica ripetutamente gli stessi pochi record: stato lavoro (Arrivato, In Corso, Fatto), parti usate, firma cliente e nuove foto. Alcune modifiche sono piccole e frequenti (stato). Altre sono grandi (foto) e non devono andare perse.
Il momento della sync: due persone hanno toccato lo stesso lavoro
Alle 11:10 il tecnico marchia il Lavoro #18 come Fatto e aggiunge una firma offline. Alle 11:40 un dispatcher riassegna il Lavoro #18 perché in ufficio sembra ancora aperto. Quando il tecnico si riconnette alle 12:05, l'app carica le modifiche.
Un buon flusso di conflitto non nasconde questo evento. Lo mette in evidenza. Un supervisore dovrebbe vedere un messaggio semplice: “Esistono due versioni del Lavoro #18”, con i campi chiave affiancati (stato, tecnico assegnato, timestamp, firma sì/no) e opzioni chiare: conserva l'aggiornamento locale, conserva l'aggiornamento d'ufficio o unisci per campo.
Qui le decisioni su storage e sync emergono nella vita reale: riesci a tracciare una cronologia pulita delle modifiche e riesci a riprodurle in sicurezza dopo ore offline?
Quando un lavoro “scompare”, il debug riguarda dimostrare cosa è successo. Registra abbastanza per rispondere: mapping ID record locale <-> server (inclusa data di creazione), ogni scrittura con timestamp/utente/dispositivo, tentativi di sync ed errori, decisioni sui conflitti e il vincitore, e stato di upload foto tracciato separatamente dal record lavoro.
Con quei log puoi riprodurre il problema invece di indovinare dalla lamentela.
Prossimi passi: valida in fretta, poi costruisci la soluzione completa
Prima di schierarti in dibattiti SQLite vs Realm, scrivi una specifica di una pagina per i tuoi flussi offline: le schermate che vede un tecnico, quali dati vivono sul dispositivo e cosa deve funzionare senza segnale (creare, modificare, foto, firme, upload in coda).
Poi prototipa l'intero sistema presto, non solo il database. Le app da campo falliscono nelle giunture: un form mobile che salva localmente non aiuta se il team admin non può rivedere e correggere i record, o se il backend rifiuta gli aggiornamenti in seguito.
Un piano pratico di validazione:
- Costruisci una fetta sottile end-to-end: un form offline, una vista lista, un tentativo di sync e una schermata admin.
- Esegui un test di cambiamento: rinomina un campo, dividine uno in due, invia una build di prova e verifica come si comporta l'aggiornamento.
- Simula conflitti: modifica lo stesso record su due dispositivi, sincronizza in ordini diversi e annota cosa si rompe.
- Esercita il debug sul campo: decidi come ispezionare dati locali, log e payload di sync falliti su un dispositivo reale.
- Scrivi una policy di reset: quando cancelli la cache locale e come gli utenti si riprendono senza perdere lavoro.
Se la velocità conta, un passaggio no-code iniziale può aiutare a validare il flusso rapidamente. AppMaster (appmaster.io) è una delle opzioni per costruire la soluzione completa (servizi backend, pannello admin web e app mobili) presto, poi rigenerare codice pulito man mano che i requisiti cambiano.
Scegli il prossimo passo di validazione basandoti sul rischio. Se i moduli cambiano settimanalmente, testa prima le migrazioni. Se più persone toccano lo stesso lavoro, testa i conflitti. Se temi “funzionava in ufficio”, dai priorità al tuo workflow di debug sul campo.
FAQ
Offline-first significa che l'app resta utile senza connessione: può caricare i dati necessari, accettare nuovi input e mantenere ogni modifica al sicuro fino a quando non è possibile sincronizzare. La promessa principale è che gli utenti non perdano lavoro o fiducia quando il segnale cade, il sistema operativo chiude l'app o la batteria si scarica a metà attività.
SQLite è spesso la scelta più sicura quando servono filtri complessi, query in stile report, relazioni molti-a-molti e ispezioni ad hoc facili con strumenti comuni. Realm è adatto quando si preferisce un accesso ai dati in stile oggetti, scritture transazionali di default e quando le esigenze di query possono rimanere allineate ai punti di forza di Realm.
Tratta le migrazioni come una funzionalità centrale, non come un'operazione una tantum. Installa una build vecchia, crea dati realistici sul dispositivo, poi aggiorna e conferma che l'app si apra, permetta modifiche e si sincronizzi; testa anche dataset grandi, spazio di archiviazione basso e l'interruzione dell'app a metà migrazione.
Aggiungere un campo è quasi sempre semplice in entrambi i sistemi, ma rinominare e dividere campi sono le modifiche più rischiose. Pianifica queste modifiche deliberatamente, imposta valori predefiniti sensati, gestisci con cura i null e evita migrazioni che riscrivono ogni record in un colpo solo su dispositivi datati.
Le schermate di elenco e i filtri che rispecchiano il lavoro reale sono il metro più importante: “i lavori di oggi”, “moduli non sincronizzati”, “modificati nelle ultime 2 ore” e una ricerca veloce. Se esprimere queste query è scomodo, l'interfaccia rallenterà o il codice diventerà difficile da mantenere.
Né SQLite né Realm risolvono i conflitti da soli; serve comunque una regola di business. Inizia scegliendo una regola chiara per tipo di entità (last write wins, merge per campo o coda di revisione manuale) e fai sì che l'app sia in grado di spiegare cosa è successo quando due dispositivi modificano lo stesso record.
Registra metadati sufficienti per spiegare e riprodurre le modifiche: ID utente, ID dispositivo, timestamp e un marcatore “last changed” per record. Mantieni un log locale delle operazioni così da vedere cosa è stato messo in coda, cosa è stato inviato, cosa è fallito e cosa il server ha accettato.
SQLite è facile da ispezionare perché è un file che puoi recuperare dal dispositivo e interrogare direttamente, il che aiuta con analisi ad hoc ed esportazioni. L'ispezione di Realm spesso si sente più naturale per grafi di oggetti e relazioni, ma i team abituati a SQL possono trovare l'analisi profonda meno flessibile.
I rischi maggiori non derivano quasi mai dal motore di database: sono nella logica dell'app. Scritture in più passaggi senza un punto di commit chiaro, errori di sincronizzazione nascosti e assenza di una strada di recupero per scenari di disco pieno o corruzione causano perdita di dati. Usa transazioni/checkpoint, mostra chiaramente stato di salvataggio e sincronizzazione, e prevedi un’opzione prevedibile di “reset e risincronizzazione” che non richieda la reinstallazione.
Costruisci uno scenario realistico end-to-end e misuralo: primo caricamento con migliaia di record, ricerca, salvataggi lunghi e una sincronizzazione dopo un giorno offline. Valida gli aggiornamenti da almeno due build più vecchie, simula conflitti con due dispositivi e conferma di poter ispezionare lo stato locale e i log quando qualcosa va storto.


