Importazioni batch sicure: anteprima, convalida e commit
Le importazioni batch sicure aiutano a evitare dati errati e modifiche indesiderate. Usa anteprima, convalida, segnalazioni per riga e modelli di commit che facilitano il rollback.

Perché le modifiche in massa vanno storte (e cosa si aspettano gli utenti)
Le modifiche in massa falliscono per motivi banali e reali. Il file è quasi giusto, ma il nome di una colonna è sbagliato. Un campo obbligatorio è vuoto in qualche riga. Gli ID non corrispondono al database perché qualcuno ha esportato la scorsa settimana e i record sono cambiati nel frattempo. Oppure i dati sono validi, ma mappati nel campo sbagliato, così i numeri di telefono finiscono nella colonna note.
Ciò che rende tutto spaventoso è la velocità. Un’unica ipotesi sbagliata può toccare centinaia o migliaia di record prima che qualcuno se ne accorga. Le importazioni batch sicure non sono solo un problema di backend: sono un problema di fiducia.
Gli utenti si aspettano una cosa semplice: mostrami cosa succederà prima che succeda. Il modello più affidabile è anteprima, convalida, poi commit.
- Anteprima: mostra un riepilogo chiaro e un campione delle modifiche effettive.
- Convalida: esegui regole che rilevino campi mancanti, formati errati e riferimenti non corrispondenti.
- Commit: applica le modifiche solo dopo che l’utente conferma, usando un approccio adeguato al rischio.
Le persone si aspettano anche protezione da due tipi di guasto.
Problemi correggibili dovrebbero essere gestiti per riga. Se 12 righe hanno un formato email non valido o manca il CAP, l’utente vuole correggere quelle righe (scaricare un report, modificare in loco o ricaricare) e tenere pronte le altre.
Problemi bloccanti devono fermare tutto. Se il mapping è sbagliato, l’import sovrascriverebbe campi chiave, o il file è per il workspace o il cliente sbagliato, la migliore esperienza è uno stop netto con una spiegazione chiara.
Gli utenti vogliono anche una traccia: un run ID, timestamp, chi l’ha lanciato, quale file è stato usato, cosa è cambiato e cosa è fallito. Questo accelera il supporto e rende possibile il ripristino quando qualcosa va storto.
Il flusso anteprima-convalida-commit in termini semplici
Le modifiche in massa sembrano rischiose perché un click può toccare migliaia di record. Il modo più semplice per ridurre il rischio è dividere il lavoro in tre fasi, ciascuna con il proprio output.
Fase 1: Anteprima (prepara il batch)
Prendi l’input (CSV, righe incollate, record selezionati) e trasformalo in un batch preparato. Lo scopo qui è mostrare cosa il sistema pensa succederà, prima che nulla cambi.
Una buona anteprima risponde a tre domande: cosa verrà cambiato, quanti elementi sono coinvolti e cosa sembra sospetto.
Al minimo, includi conteggi (righe totali, record corrispondenti, record nuovi, righe saltate), un piccolo campione di righe reali e avvisi chiari per tutto ciò che è a rischio (campi obbligatori mancanti, corrispondenze ambigue, valori insoliti). Rendila esplicita sulla regola di matching (per esempio, “matching per email” o “matching per external ID”), e dai al batch un’identità: un nome, timestamp e un batch ID unico.
Fase 2: Convalida (dry run)
Un dry run significa nessuna scrittura sul database. Esegui gli stessi controlli che userai durante l’aggiornamento reale, ma produci solo un report.
La convalida dovrebbe coprire sia regole per riga (questa riga è valida?) sia regole cross-riga (queste righe si confliggono?). L’output non dovrebbe essere un vago ok/ko. Deve essere un riepilogo più un elenco di problemi legati a righe specifiche, così le persone possono risolvere i problemi senza indovinare.
Fase 3: Commit (applica le modifiche)
Il commit è il punto di non ritorno, quindi dovrebbe essere disponibile solo dopo un dry run riuscito. L’utente non conferma semplicemente “il file”. Sta confermando uno specifico batch preparato che è stato anteprimeato e convalidato.
Questo punto decisionale è importante. Se il file cambia, il mapping cambia o i dati vengono ricaricati, crea un nuovo batch e chiedi di confermare di nuovo.
Esempio: importi 5.000 clienti. L’anteprima mostra 4.920 corrispondenze per email, 60 nuovi, 20 saltati per email mancante. Il dry run segnala 12 righe con formato telefono non valido. Solo dopo che quelle 12 sono sistemate il pulsante “Commit batch” diventa disponibile per quel preciso batch ID.
Input, mapping e come identifichi i record
Molti job in massa falliscono prima ancora che la convalida inizi. L’input è disordinato, le colonne non corrispondono ai tuoi campi, o il sistema non sa se una riga deve creare un record nuovo o aggiornare uno esistente.
Le operazioni in massa di solito partono da un export CSV, righe incollate da spreadsheet, record selezionati nell’app (mass update) o un job batch attivato via API. Qualunque sia la fonte, serve un mapping chiaro da “ciò che l’utente ha” a “ciò che il sistema memorizza”.
Il mapping dovrebbe coprire l’accoppiamento colonna→campo, piccole trasformazioni (trim degli spazi, parsing delle date, normalizzazione dei telefoni) e valori di default per i campi mancanti. Non nascondere cosa succede quando una colonna è vuota. Gli utenti devono sapere se una cella vuota lascia il valore esistente, lo cancella o applica un default.
L’identità è la decisione successiva: come abbini ogni riga a un record esistente?
Preferisci identificatori stabili e sii esplicito su cosa accade quando non c’è corrispondenza o ce ne sono più d’una. Scelte comuni includono ID interni (i migliori, se gli utenti possono esportarli), ID di sistemi esterni (ottimi per integrazioni) ed email (utili, ma attenzione ai duplicati e al case). A volte una chiave composta è la scelta giusta, come account_id + invoice_number. In altri casi puoi offrire una modalità “create only” che non fa matching e crea sempre nuovi record.
Infine, applica regole di permesso su scala. Chi può modificare un record non dovrebbe automaticamente poter aggiornare ogni campo su migliaia di record. Decidi quali ruoli possono eseguire import, quali campi è permesso cambiare e quando serve un’approvazione aggiuntiva.
Progettare un’anteprima che generi fiducia
L’anteprima è dove le persone decidono se si sentono sicure a premere “Commit”. Se l’anteprima è vaga, gli utenti presumono che il sistema stia indovinando. Una buona anteprima si legge come una ricevuta: cosa cambierà, quanto è sicuro il sistema e cosa bloccherà l’aggiornamento.
Inizia con un riepilogo conciso. La maggior parte degli utenti ha bisogno di pochi numeri per orientarsi: righe totali, quante saranno saltate, crea vs aggiorna (e cancella se le permetti), quante righe hanno avvisi vs errori bloccanti, e la regola di matching usata (per esempio, “matched by email”). Se possibile, raggruppa le categorie di avvisi più comuni così gli utenti vedono i pattern rapidamente.
Poi lascia che le persone ispezionino i dati reali. Mostra un piccolo campione scrollabile e includi una vista prima vs dopo per gli aggiornamenti. Vedere “vecchio valore → nuovo valore” previene sorprese come sovrascrivere un telefono con una cella vuota. Un pattern UI pratico è mostrare 10–50 righe con ricerca e filtri (es. “solo avvisi”), mentre il file completo viene processato in background.
L’incertezza deve essere visibile. Se una riga potrebbe corrispondere a più record, dillo e mostra i candidati. Se un campo obbligatorio è vuoto, indica la cella esatta. Se l’import potrebbe creare duplicati, evidenzialo con una breve ragione (per esempio, “stessa email appare due volte nel file”). Le persone si fidano di più quando il sistema ammette ciò che non può sapere.
Rendi anche chiare le azioni successive. Gli utenti dovrebbero poter scaricare un report di errori con numeri di riga e messaggi precisi, correggere e ricaricare senza ricostruire il mapping, annullare senza modifiche, o procedere solo quando il rischio è basso e hanno i permessi necessari.
Regole di convalida che intercettano problemi precocemente
Una buona validazione è ciò che fa sembrare calme le importazioni in massa invece che rischiose. L’obiettivo è trovare problemi prima che qualcosa cambi e spiegarli in modo che possano essere risolti.
Suddividi la convalida in tipi chiari
Un unico messaggio generico “non valido” crea confusione. Tratta i controlli come cestini separati perché ciascuno suggerisce una correzione diversa.
I controlli di formato coprono tipi, formati di data, intervalli numerici e pattern di telefono/email. I controlli sui campi obbligatori intercettano valori mancanti, stringhe vuote e casi ambigui come 0 vs vuoto. I controlli referenziali verificano che gli ID esistano e che gli stati siano consentiti. Le regole di business applicano vincoli reali: limiti di credito, permessi di ruolo o “non si può chiudere un ordine con voci aperte”.
Una regola chiave: valida usando la stessa logica che userai al commit. Se anteprima e commit seguono regole diverse, la fiducia si rompe rapidamente. Riusa gli stessi validator, le stesse lookup sui dati e gli stessi controlli di permesso end-to-end.
Rendi la convalida veloce e prevedibile
I file grandi possono richiedere tempo, quindi la convalida deve risultare reattiva. Valida a blocchi (per esempio 500–2.000 righe), mostra progresso e stima dei tempi, e metti in cache i dati di riferimento riutilizzati così non richiami ripetutamente le stesse liste di ID.
Le regole cross-riga richiedono cura speciale perché richiedono di vedere l’intero upload. Esempi comuni sono duplicati interni al file (stessa email due volte) o conflitti (due righe cercano di impostare valori diversi per lo stesso record). Costruisci un indice leggero durante il parsing, poi segnala entrambe le righe coinvolte così l’utente può scegliere cosa mantenere.
Errori a livello di riga: rendili azionabili, non spaventosi
Gli errori a livello di riga sono dove si conquista o si perde la fiducia. Una parete di testo rossa blocca le persone. Elementi chiari e correggibili le fanno andare avanti.
Inizia separando le severità. Un errore bloccante significa che la riga non può essere applicata così com’è (campo obbligatorio mancante, formato non valido, record non trovato). Un avviso significa che la riga può essere applicata, ma l’utente dovrebbe scegliere (il valore verrà trim- mato, si applicherà un default, esiste un possibile duplicato).
Un buon feedback per riga è specifico e ripetibile. Ogni problema dovrebbe includere un identificatore di riga (numero di riga nel file più una chiave stabile come email o ID esterno), il nome del campo (colonna e campo di destinazione), un messaggio semplice (“Phone deve essere in formato E.164”, non “Validation failed”), e una correzione suggerita (un valore di esempio o intervallo consentito). Mantieni consistenti i tag di severità.
Il successo parziale deve essere un’opzione deliberata, non un incidente. Consentilo solo quando le righe sono indipendenti e il risultato non creerà uno stato corrotto. Aggiornare i tag cliente può essere parziale. Aggiornare fatture e le loro righe quasi mai.
Pianifica i retry come parte della UX. Gli utenti dovrebbero poter correggere il file sorgente e rieseguire senza rifare il mapping e senza perdere il contesto. Un pattern pratico è mantenere un record “import run” che memorizza scelte di mapping e risultati riga-per-riga, così la run successiva può evidenziare “ancora in errore” vs “ora sistemato”.
Modelli di commit: atomico, parziale e idempotente
Il commit è il momento in cui le importazioni guadagnano o perdono fiducia. Gli utenti hanno già visto l’anteprima e risolto problemi. Ora si aspettano che il sistema applichi esattamente ciò che è stato validato.
Scegli una modalità di commit e dichiarala chiaramente
Due modalità di commit sono comuni e entrambe vanno bene se la regola è chiara.
Atomico (tutto-o-nulla) significa che se una riga fallisce, nulla viene scritto. È l’ideale per soldi, inventario, permessi e tutto ciò che deve rimanere coerente. Commit parziale (best-effort) applica le righe valide e salta quelle non valide, segnalando gli errori. È spesso adatto per aggiornamenti CRM o arricchimento profili dove qualche progresso è meglio di niente. Alcuni team usano una soglia ibrida: commit solo se i fallimenti restano sotto un limite (per esempio, ferma se più del 2% fallisce).
Qualunque sia la scelta, rendila visibile nella schermata di commit e nel riepilogo finale.
Lega il commit al batch convalidato
Usa un job ID di import (batch ID) creato in fase di anteprima. La richiesta di commit dovrebbe fare riferimento a quell’ID, non ai dati ricaricati.
Questo evita un errore comune: qualcuno anteprima un file, poi ne carica un altro e poi preme commit. Aiuta anche quando più amministratori lavorano contemporaneamente.
Idempotenza: proteggi contro la doppia applicazione
Le persone fanno doppio click. I browser ritentano. Le tab si ricaricano. Un commit deve essere sicuro da eseguire più volte.
L’approccio più semplice è l’idempotenza: usa una chiave di idempotency unica per job (e per riga quando serve), usa upsert dove il modello dati lo permette e blocca lo stato del job così può passare da Validato → Committing → Committato solo una volta.
Registra gli esiti come una ricevuta
Dopo il commit, mostra un riepilogo conciso e lascia scaricare o copiare i risultati. Includi conteggi per creati, aggiornati, saltati e falliti, più brevi motivi. Questo trasforma una modifica di massa spaventosa in qualcosa che gli utenti possono verificare e spiegare.
Piani di rollback che funzionano nella pratica
Un piano di rollback trasforma le importazioni in massa da “speriamo che funzioni” a qualcosa che puoi eseguire anche di lunedì mattina. Se i risultati sono sbagliati, dovresti poter tornare allo stato precedente senza indovinare cosa è cambiato.
L’approccio giusto dipende dalla dimensione del batch, da quanto tempo impiega l’operazione e se tocchi sistemi esterni (email, pagamenti, messaggi) che non si possono annullare.
Tre approcci pratici al rollback
Per batch piccoli e veloci, una singola transazione database è il modo più semplice. Applica tutte le modifiche e, se un passo fallisce, il database scarta tutto. Funziona bene per poche centinaia o migliaia di righe quando aggiorni solo le tue tabelle PostgreSQL.
Per import più grandi, lo staging-first è di solito più sicuro. Carica il file in una tabella di staging, convalidalo lì e poi promuovi i dati nella produzione. Se qualcosa non va, elimina i dati di staging e nulla in produzione viene toccato. Questo rende anche i retry più semplici perché puoi mantenere il dataset di staging e aggiustare mapping o regole senza ricaricare.
Quando il rollback vero non è possibile, pianifica azioni compensative. Se il bulk update invia email o avvia pagamenti, non puoi riavvolgere il tempo. Il piano di undo potrebbe essere “marca i record come annullati”, “emetti rimborsi” o “invia un messaggio di correzione”. Definisci i passaggi di undo prima di eseguire il job, non dopo.
Una regola semplice per scegliere:
- Usa una transazione singola quando il batch è piccolo e tocchi solo il tuo database.
- Usa staging e promozione quando il batch è grande, lento o ad alto rischio.
- Usa azioni compensative quando inneschi effetti esterni.
- Hai sempre un piano di re-run ripetibile così lo stesso input non applica doppi cambiamenti.
I log di audit rendono il rollback realistico
Il rollback dipende dal sapere esattamente cosa è successo. Cattura chi ha eseguito il job, quando è stato eseguito, il file sorgente o job ID e quali record sono cambiati (valori prima/dopo, o almeno un sommario dei cambiamenti).
Esempio concreto: un lead del support bulk-aggiorna 5.000 stati cliente. Con lo staging individuano 200 righe non corrispondenti prima della promozione. Se successivamente scoprono che il mapping era invertito, il log di audit permette di eseguire un revert mirato solo per i record interessati invece di fare rollback sull’intero sistema.
Errori comuni e trappole da evitare
I job in massa falliscono in modi prevedibili. La maggior parte dei problemi non è “dati sporchi”, ma aspettative non corrisposte: l’utente pensava che sarebbe successo X e il sistema ha fatto Y.
Una trappola importante è validare con un set di regole e committare con un altro. Succede quando l’anteprima usa controlli rapidi (o un servizio diverso) e il percorso di commit ha vincoli o default differenti. Gli utenti vedono “tutto ok”, poi il job reale fallisce, o peggio, riesce con risultati diversi. Mantieni un parser condiviso, un unico set di regole e la stessa logica di matching end-to-end.
Una logica di matching poco chiara è un altro classico fallimento. “Match by email” sembra semplice finché non incontri duplicati, differenze di case o utenti che hanno cambiato email. La UI deve dichiarare esattamente come funziona il matching e cosa succede con più hit o nessun hit. Esempio: un admin sales importa 2.000 contatti aspettandosi aggiornamenti, ma il sistema crea nuovi record perché il matching controllava solo l’email e metà del file usa i numeri di telefono.
Fai attenzione alle “autocorrezioni utili”. Troncamenti silenziosi, trim automatico o tentativi di indovinare formati data possono nascondere perdita di dati. Se normalizzi valori, mostralo nell’anteprima (vecchio valore → nuovo valore) e segnala conversioni rischiose. Se un campo verrà tagliato per rispettare un limite, fallo vedere come avviso.
Non far perdere agli utenti l’esito. Se chiudono la tab e il report sparisce, arrivano ticket di supporto. Memorizza ogni import run come un oggetto con stato, file di risultati e riepilogo chiaro.
Pianifica anche la scalabilità. Senza batching emergono timeout e scritture parziali sotto volumi reali. Proteggi il sistema con batching e aggiornamenti di progresso, rate limits e backoff, chiavi di idempotency, gestione chiara del successo parziale e un’opzione salvata per “rilanciare le righe fallite”.
Una checklist semplice e passi successivi
Le modifiche in massa sembrano sicure quando tutti sanno cosa succederà, cosa potrebbe andare storto e come notare problemi rapidamente.
Controlli preflight veloci (prima che qualcuno prema Commit)
Fai un reality check sui dati, non solo sulla UI. Scegli poche righe che rappresentino i casi comuni e i casi limite.
- Controlla un piccolo campione (per esempio 20 righe): nomi, date e numeri sembrano corretti.
- Conferma che il mapping dei campi corrisponda alle colonne sorgente (e che le celle vuote facciano ciò che intendi).
- Verifica la chiave di match (email, SKU, external ID) che sia sufficientemente unica e presente.
- Confronta i totali: quante righe creeranno, aggiorneranno o salteranno.
- Leggi gli avvisi ad alta voce così tutti concordano che sono accettabili.
Fai una pausa per una decisione umana. Se un’importazione tocca clienti, fatturazione o inventario, fai approvare l’anteprima e i conteggi da un responsabile. Se un sales manager si aspetta 1.200 contatti aggiornati e la tua anteprima mostra 12.000, non procedere finché non si capisce perché.
Controlli dopo il commit (così i problemi non restano in sospeso)
Una volta che il commit termina, verifica di nuovo la realtà, ma resta concentrato.
- Apri un piccolo insieme di record aggiornati e conferma che i campi chiave siano cambiati correttamente.
- Esporta un report dei risultati con stato per riga, ID creati e eventuali errori.
- Registra cosa è successo: chi l’ha eseguito, quando, quale file/versione e i conteggi di riepilogo.
- Se ci sono errori, decidete in fretta: ripeti le righe fallite o esegui il rollback.
Se stai costruendo questo workflow in una piattaforma no-code, aiuta trattare gli import come una vera feature di prodotto, non come uno script admin fatto una volta. Per esempio, in AppMaster (appmaster.io) i team spesso modellano un record Import Run in PostgreSQL, implementano la logica di dry-run e commit nel Business Process Editor e mantengono una traccia di audit chiara in modo che gli aggiornamenti in massa restino ripetibili e supportabili.
FAQ
Usa un flusso in tre fasi: anteprima, convalida, poi commit. L’anteprima mostra cosa cambierà, la convalida esegue un dry run con le stesse regole del commit, e il commit diventa disponibile solo dopo che la convalida è passata per quello specifico batch.
Un’anteprima permette agli utenti di vedere errori evidenti prima che qualcosa venga scritto: mapping sbagliato, conteggi crea vs aggiorna inaspettati, o celle vuote che sovrascriverebbero dati. Dovrebbe mostrare totali e un piccolo campione "prima e dopo" per verificare l’impatto.
Una convalida in dry run applica lo stesso parsing, matching, controlli di permesso e regole di business dell’aggiornamento reale, ma non scrive nel database. L’output deve essere un riepilogo chiaro più problemi riga-per-riga in modo che si possano correggere gli errori senza indovinare.
Blocca tutto quando il job è globalmente pericoloso, ad esempio workspace sbagliato, mapping che sovrascrive campi chiave o altre condizioni che rendono l’import insicuro. Per problemi correggibili su poche righe (es. formato telefono errato), permetti la correzione riga-per-riga e lascia pronti gli altri record per il commit.
Sii esplicito sulla chiave di match e su cosa succede in caso di nessun match o di match multipli. ID interni sono i migliori, gli ID esterni funzionano bene per integrazioni, e l’email può andare bene ma richiede gestione dei duplicati e normalizzazione coerente.
Non nasconderlo. Decidi una regola chiara per ogni campo: ad esempio “vuoto lascia il valore esistente” per aggiornamenti, oppure “vuoto cancella il valore”. Mostra questa regola nell’anteprima così gli utenti non vengono sorpresi da perdita di dati silenziosa.
Mostra numero di riga più un identificatore stabile come email o ID esterno, indica la colonna e il campo di destinazione, e fornisci un messaggio semplice che suggerisca la correzione. L’obiettivo è permettere all’utente di riparare il file sorgente rapidamente e rilanciare senza interpretare messaggi criptici.
I commit atomici sono preferibili quando serve consistenza (soldi, inventario, permessi): qualsiasi errore annulla tutto. I commit parziali vanno bene per aggiornamenti indipendenti come l’arricchimento di contatti, purché l’interfaccia indichi chiaramente che alcune righe possono essere saltate e segnalate.
Usa una chiave di idempotency legata al batch convalidato e blocca lo stato del job così può passare solo una volta da Validato → Commit in corso → Committato. Questo protegge da doppio click, retry e refresh che altrimenti applicherebbero le stesse modifiche due volte.
Modella un record Import Run in PostgreSQL, memorizza batch ID, scelte di mapping, risultati della validazione e outcome finali, quindi implementa la logica di dry-run e commit in un Business Process. Questo crea un processo ripetibile con traccia di audit e semplifica il supporto se qualcosa va storto.


