f in x
Data Retention GDPR: Cancellazione Automatica e Soft Delete per Sviluppatori
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Considerazioni legali ed etiche

Data Retention GDPR: Cancellazione Automatica e Soft Delete per Sviluppatori

[2026-06-15] Author: Ing. Calogero Bono

Hai un database che accumula dati di utenti inattivi, ordini cancellati, log di accesso vecchi di anni. Il GDPR impone limiti di conservazione precisi, ma cancellare fisicamente i dati è rischioso: se un cliente chiede il ripristino, se un audit richiede uno storico, se un pagamento è contestato. Il soft delete è la soluzione tecnica che concilia compliance e operatività. Ma senza un processo automatico di rimozione definitiva, rischi di accumulare dati fantasma che violano il principio di minimizzazione. Noi di Meteora Web vediamo quotidianamente aziende che implementano soft delete senza un piano di retention. Risultato: tabelle gonfie, backup lenti, vulnerabilità privacy. In questa guida ti mostriamo come progettare un sistema di data retention che bilanci soft delete e cancellazione automatica, con codice funzionante e logica conforme al GDPR.

Soft Delete e Hard Delete: Quando Usare Ciascuno

Il soft delete marca un record come cancellato senza rimuoverlo fisicamente. Si implementa con un campo deleted_at (Laravel) o is_deleted, e si esclude dalle query standard. Il vantaggio è il ripristino rapido e la tracciabilità. Lo svantaggio? I dati restano nel database. L'hard delete rimuove il record in modo irreversibile. È obbligatorio quando il periodo di retention è scaduto e non ci sono obblighi legali (es. fatture).

Quale scegliere per ogni tipo di dato

Non esiste una risposta unica. Ecco come lo gestiamo noi nei progetti reali:

Sponsored Protocol

  • Dati personali (utenti, contatti): soft delete per 30-90 giorni (periodo finestra di ripristino), poi hard delete automatico.
  • Ordini e fatture: soft delete permanente? No. Per obblighi fiscali (es. 10 anni) tieni i dati, ma anonimizza i campi personali (nome, email).
  • Log di accesso: hard delete dopo 6 mesi, salvo obblighi di sicurezza (es. PCI-DSS richiede 1 anno).
  • Sessioni e token: hard delete immediato alla scadenza, nessun soft delete.

GDPR e Data Retention: I Limiti Legali

L'articolo 5(1)(e) GDPR richiede che i dati siano conservati per un tempo non superiore a quello necessario. Ogni finalità ha una durata diversa. Come sviluppatore, devi tradurre questi vincoli in regole automatizzate. Non puoi lasciare la decisione ai singoli operatori.

Mappatura Finalità-Retention

Prima di scrivere una riga di codice, mappa ogni entità del database con:

  • Finalità di trattamento
  • Base giuridica
  • Periodo di conservazione
  • Eventuale obbligo di anonimizzazione

Crea una tabella di configurazione esterna (JSON, DB, env) modificabile senza deploy. Esempio:

{
  "users": {
    "purpose": "account management",
    "retention_days": 365,
    "soft_delete_days": 30,
    "action_after_retention": "anonymize"
  },
  "order_logs": {
    "purpose": "transaction history",
    "retention_days": 3650,
    "soft_delete_days": 0,
    "action_after_retention": "hard_delete"
  }
}

Noi usiamo un pattern simile per tutti i clienti. Consente di adattare le policy senza toccare il codice.

Sponsored Protocol

Implementazione Pratica: Soft Delete con Laravel e SoftDeletes

Laravel fornisce il trait SoftDeletes. Usiamolo per gestire il primo livello di cancellazione.

Modello con SoftDeletes

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class User extends Model
{
    use SoftDeletes;
    protected $dates = ['deleted_at'];
}

Quando chiami $user->delete(), Laravel imposta deleted_at con il timestamp. Le query normali escludono questi record (grazie al global scope). Puoi recuperarli con User::withTrashed()->find($id) e ripristinarli con $user->restore().

Cancellazione Automatica: Scheduler e Comandi Artisan

Il soft delete non basta. Dopo il periodo di retention (es. 30 giorni di soft delete + 365 di retention totale) devi rimuovere fisicamente i dati. Creiamo un comando Artisan.

// app/Console/Commands/PurgeSoftDeletedRecords.php
namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\User;
use App\Models\Order;
use Carbon\Carbon;

class PurgeSoftDeletedRecords extends Command
{
    protected $signature = 'retention:purge';
    protected $description = 'Elimina fisicamente i record soft-deleted scaduti';

    public function handle()
    {
        $config = config('retention'); // tabella di mapping
        foreach ($config as $modelClass => $rules) {
            $deadline = Carbon::now()->subDays($rules['retention_days'] - $rules['soft_delete_days']);
            // I record soft-deleted prima della deadline vanno eliminati
            $query = $modelClass::onlyTrashed()
                ->where('deleted_at', '<', $deadline);
            $count = $query->count();
            $query->forceDelete();
            $this->info("Eliminati {$count} record da {$modelClass}");
        }
    }
}

Registra il comando in app/Console/Kernel.php e programmalo giornalmente:

Sponsored Protocol

protected function schedule(Schedule $schedule)
{
    $schedule->command('retention:purge')
             ->dailyAt('03:00')
             ->withoutOverlapping();
}

Gestione della Retention su Database non-Laravel (PHP/SQL)

Se non usi Laravel, puoi implementare lo stesso pattern con query dirette. Esempio MySQL:

-- Aggiungi campo deleted_at alla tabella users
ALTER TABLE users ADD COLUMN deleted_at TIMESTAMP NULL DEFAULT NULL;

-- Query per eliminare fisicamente i record soft-deleted più vecchi di 30 giorni
DELETE FROM users
WHERE deleted_at IS NOT NULL
AND deleted_at < NOW() - INTERVAL 30 DAY;

-- Query per soft delete (marcatura)
UPDATE users SET deleted_at = NOW() WHERE id = ?;

Per automatizzare, usa un cron job:

Sponsored Protocol

# crontab -e
0 3 * * * php /path/to/purge.php

Il file purge.php leggerà la configurazione ed eseguirà le DELETE condizionate.

Anonimizzazione vs Cancellazione

In alcuni casi (es. fatture) non puoi cancellare il record, ma puoi anonimizzare i dati personali. Un campo email diventa redatto-{id}@dominio.internal, il nome Utente Cancellato. Implementiamo un comando separato per l'anonimizzazione.

// Comando di anonimizzazione
public function handle()
{
    $users = User::where('deleted_at', '<', Carbon::now()->subDays(60))->get();
    foreach ($users as $user) {
        $user->email = 'anonimo-'.$user->id.'@example.com';
        $user->name = 'Utente Cancellato';
        $user->save();
    }
}

Importante: l'anonimizzazione deve essere irreversibile. Non salvare l'email originale da nessuna parte.

Monitoraggio e Logging

Una retention automatica senza audit è pericolosa. Registra ogni azione di hard delete o anonimizzazione in un log non cancellabile (es. syslog, tabella separata con INSERT only). Noi consigliamo di loggare:

  • Data e ora dell'operazione
  • Numero di record interessati
  • Intervallo di date
  • Comando eseguito (o job ID)

Inoltre, aggiungi un allarme se il comando non viene eseguito per più di 48 ore (es. via monitoring esterno o check interno). Un fallimento dello scheduler può portare a violazioni GDPR.

Sponsored Protocol

Checklist per l'Implementazione

  1. Mappa tutte le entità con finalità, retention, soft delete e azione finale.
  2. Implementa soft delete per i dati che potrebbero necessitare ripristino (utenti, contenuti, ordini parziali).
  3. Crea comandi automatici per hard delete dopo la finestra di soft delete.
  4. Gestisci l'anonimizzazione per i dati che devono restare per obblighi contabili.
  5. Configura lo scheduler e monitora l'esecuzione.
  6. Testa su staging con un set di dati campione.
  7. Documenta le policy e tienile aggiornate nel registro dei trattamenti.

In Sintesi — Cosa Fare Subito

Non aspettare un audit. Oggi stesso:

  1. Identifica 3 tabelle del tuo database che contengono dati personali.
  2. Stabilisci per ciascuna il periodo di retention e la finestra di soft delete.
  3. Scrivi un comando semplice (anche SQL via cron) che pulisca i record oltre la finestra.
  4. Aggiungi un log dell'operazione.
  5. Verifica che lo scheduler sia attivo (su server Linux: systemctl status cron).

Se ti serve un approccio strutturato, abbiamo scritto la guida pillar GDPR per sviluppatori dove approfondiamo anche cookie, consenso e diritto all'oblio. La data retention è solo un pezzo del puzzle — ma se fatta male, può costarti caro. Noi di Meteora Web lo vediamo ogni giorno: un hard delete sbagliato e perdi clienti, un soft delete infinito e rischi sanzioni. Progetta con cura, automatizza con rigore.

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()