Un client conteste un montant facturé trois mois plus tôt. La fiche affiche aujourd’hui le bon tarif, mais personne ne sait quelle valeur était applicable à la date de commande, qui l’a changée ni pourquoi. Les logs ont tourné, une sauvegarde existe peut-être, et l’équipe tente de reconstituer la décision depuis des captures d’écran.
Historiser toutes les tables paraît alors prudent. Cette réponse peut pourtant dupliquer des volumes, exposer des données sensibles plus longtemps et produire une masse inutilisable. À l’inverse, garder uniquement la dernière valeur rend certains contrats, droits et diagnostics impossibles à défendre. Le besoin n’est pas « tout conserver » ; il est de répondre à des questions définies.
Le vrai enjeu est de réduire le risque d’une décision impossible à expliquer. Un bon historique distingue trace d’accès, audit de modification, versions métier et événements de domaine. Il porte la date d’effet, la date de connaissance, l’auteur et la cause lorsque ces dimensions comptent. Il prévoit aussi la lecture, la sécurité, la correction et la suppression. Une donnée conservée sans moyen fiable de l’interpréter n’est pas une preuve.
Dans une application de développement web sur mesure, ce choix relie produit, architecture, conformité et run. Voici comment dimensionner le mécanisme sans le réduire à un journal technique.
Partir de la question à reconstruire
Écrivez les questions avant le schéma : qui a changé le compte bancaire ? Quel tarif était applicable le 3 juin ? Quels droits le support voyait-il au moment de sa décision ? Comment l’objet est-il arrivé dans cet état ? Ces formulations ne demandent pas les mêmes données ni la même garantie.
Associez chaque question à un acteur, une fréquence, un délai de réponse et une conséquence. Un diagnostic quotidien exige une lecture rapide. Une preuve rare mais sensible privilégie intégrité et accès contrôlé. Une analyse statistique peut utiliser une projection agrégée sans exposer toutes les valeurs personnelles.
Nommer l’unité historique
Décidez si l’on versionne un attribut, un document, un agrégat ou une décision. Une copie complète de ligne simplifie parfois la lecture, mais elle mélange des champs aux durées différentes. Un événement fin explique mieux la cause, au prix d’une reconstruction plus exigeante.
Distinguer audit, version et événement
Le journal d’audit répond à qui, quand et sur quelle ressource. Il peut conserver avant et après pour les champs sélectionnés, la commande, l’acteur et le motif. Une version métier représente un état cohérent applicable à une période. Un événement affirme un fait immuable qui a eu lieu et peut déclencher des projections.
Les logs applicatifs servent au diagnostic d’exécution. Ils ne constituent pas à eux seuls un historique durable : rétention courte, format évolutif, informations techniques et absence de sémantique métier. Une sauvegarde restaure un système après incident ; elle n’offre pas une requête quotidienne ni une preuve par dossier.
Éviter l’event sourcing par réflexe
Reconstruire tout l’état depuis les événements apporte des propriétés puissantes, mais exige schémas durables, versions, projections, snapshots et compétences de run. Si la question porte seulement sur quelques attributs opposables, une table temporelle ou des versions explicites sera plus simple et plus honnête.
Modéliser le temps métier
La date d’effet indique quand la valeur vaut dans le domaine ; la date d’enregistrement indique quand le système l’a apprise. Une correction rétroactive crée donc une nouvelle connaissance sur une période ancienne. Écraser la ligne antérieure empêche de savoir quelle information avait guidé la décision initiale.
Les intervalles sont généralement demi-ouverts : début inclus, fin exclue. Cette convention évite le chevauchement d’un instant de frontière. Les types d’intervalle et contraintes d’exclusion de PostgreSQL peuvent protéger l’absence de chevauchement pour une même clé lorsque le modèle le permet.
Gérer les changements futurs
Un tarif signé aujourd’hui pour le mois prochain est une version future, pas l’état courant. Une annulation conserve la décision et son motif. Le job d’activation ne recrée pas la valeur : il rend visible une période déjà enregistrée et journalise le résultat.
Protéger intégrité et provenance
L’historique porte identifiant de l’objet, version, auteur technique et acteur métier, canal, commande et corrélation. L’utilisateur authentifié n’est pas toujours le décideur : un traitement peut appliquer une décision approuvée ailleurs. Gardez la chaîne sans inventer une responsabilité.
Les écritures d’audit doivent être atomiques avec la modification ou dérivées d’un journal transactionnel fiable. Un appel séparé peut se perdre après le commit. Les privilèges empêchent l’application ordinaire de modifier les anciennes entrées. Pour une preuve forte, envisagez stockage append-only, empreintes chaînées ou scellement externe selon le risque.
Corriger sans réécrire le passé
Une erreur historique reçoit une correction reliée à l’entrée fautive, avec auteur et motif. La vue courante applique la correction ; l’audit conserve les deux. Cette approche permet d’effacer ou pseudonymiser une donnée personnelle quand nécessaire sans prétendre que l’événement métier n’a jamais existé.
Concevoir les lectures utiles
Préparez trois vues : état à une date, chronologie des changements et différence entre deux versions. L’écran traduit les codes en libellés valables pour la version concernée et regroupe les modifications d’une même commande. Il distingue changement métier, migration, correction et synchronisation.
Les requêtes doivent éviter de relire des millions d’événements pour chaque page. Indexez objet et période, maintenez une projection courante et utilisez des snapshots si la reconstruction est longue. Le snapshot accélère ; il ne remplace pas les événements ni leur validation.
Si la chronologie sert une contestation, alors conservez l’ordre métier et la date de réception. En revanche, une liste d’activités récente peut accepter une projection reconstruite. Dans ce cas, documentez son délai. À éviter : promettre une lecture immédiate depuis une projection asynchrone sans afficher sa fraîcheur.
Rendre le motif actionnable
« Mise à jour API » n’aide personne. Le motif relie ticket, commande métier ou règle automatique. Le support doit pouvoir partir du dossier, retrouver la décision et comprendre l’effet sans accès à la console de production. Les valeurs sensibles restent masquées selon ses droits.
Cas concret : tarif contractuel corrigé
Un contrat possède un tarif de 80 euros du 1er janvier au 30 juin, puis 90 euros à partir du 1er juillet. Le 15 août, l’équipe découvre que l’avenant appliquait 88 euros depuis le 1er juillet. La table courante seule ne peut expliquer les factures déjà émises ni les informations connues au moment de leur calcul.
Le modèle crée une correction enregistrée le 15 août, effective au 1er juillet, reliée à l’avenant. Les factures restent immuables ; un calcul d’écart propose avoir ou régularisation. La vue bitemporelle répond au tarif valable et au tarif connu à une date. L’audit conserve auteur, motif et approbation.
La recette porte vingt contrats et quatre corrections rétroactives. Elle vérifie absence de chevauchement, reconstruction des montants, droits d’accès et génération d’une compensation unique. Le go local exige zéro période ambiguë et une explication support en moins d’un parcours documenté ; ce seuil est qualifié pour ce risque, pas vendu comme norme générale.
Fermer conservation et effacement
Conserver davantage n’est pas automatiquement plus conforme. Le principe de limitation de conservation figure dans l’article 5 du RGPD publié sur EUR-Lex. Définissez finalité, durée, base applicable, accès et suppression avec les personnes compétentes ; un historique technique n’accorde pas une conservation illimitée.
Classez les champs. Une identité de décideur peut devoir être conservée plus longtemps qu’une adresse IP ou qu’une valeur de contact. Pseudonymisez lorsque la question peut rester satisfaite. L’effacement doit se propager aux projections, exports et environnements de test, selon les obligations et exceptions réellement applicables.
Tester la politique de purge
Le job de purge produit un manifeste, des compteurs et des erreurs. Il est idempotent et reprend après interruption. Une restauration de sauvegarde réapplique les suppressions requises. La politique est vérifiée sur un échantillon, pas supposée parce qu’une colonne de date existe.
Implémenter une histoire exploitable
Les entrées sont commande, identité, version attendue, acteur, motif et date d’effet. La transaction écrit l’état courant et l’entrée historique ou une boîte de sortie. Les sorties exposent nouvelle version, corrélation et événements. Les dépendances, schémas et contrats restent versionnés.
Le monitoring suit trous de version, événements sans projection, délais, taille, échecs de purge et accès refusés. Le retry est idempotent ; un doublon ne crée pas deux versions. Le rollback d’un déploiement conserve les écritures déjà valides et désactive le nouveau lecteur. Une migration arrière transforme explicitement les données si nécessaire.
Migrer l’histoire existante
Ne fabriquez pas une précision absente. Marquez l’état initial comme importé avec source et date de connaissance. Si plusieurs snapshots existent, construisez les périodes certaines et placez les ambiguïtés en revue. Les tests comparent état courant, nombre de versions et échantillons sensibles.
Surveiller volumes et lacunes
Estimez volume depuis fréquence de changement, taille et durée, puis mesurez en production. Partitionnement, compression et archivage peuvent réduire le coût, mais compliquent lecture et purge. Gardez un budget par objet et alertez sur une hausse qui signale une boucle ou un champ bruyant.
Contre-intuitivement, historiser chaque recalcul peut diminuer la lisibilité. Conservez les entrées et la version de règle si le résultat est reproductible ; gardez le résultat lorsqu’il est opposable ou dépend d’une source volatile. L’arbitrage porte sur la décision à prouver, pas sur la facilité de copier une ligne.
Prévoir les enquêtes sans exposer tout le journal
Une vue d’enquête sélectionne les champs pertinents, justifie l’accès et exporte un dossier scellé. Elle évite de donner une lecture globale de toutes les anciennes valeurs à chaque opérateur. Les accès sensibles sont journalisés et revus. Pour le quotidien, l’interface support montre seulement la chronologie nécessaire à la résolution, avec masquage des données qui ne participent pas à la décision.
Mesurez aussi les questions restées sans réponse. Un événement manquant, une version sans motif ou une période ambiguë produit une lacune catégorisée. Le propriétaire décide si elle exige une correction, une meilleure instrumentation ou une limite explicitement affichée. Cet indicateur de capacité explicative est plus utile que le seul volume d’entrées écrites.
Pour qui l’historique devient nécessaire
L’historisation est prioritaire pour les données qui gouvernent argent, droits, engagements, identité, sécurité ou décisions difficiles à reproduire. Produit, métier, développeurs, sécurité, data, support et conformité doivent fermer ensemble questions, accès et durées.
Un contenu éditorial corrigé occasionnellement peut se contenter de versions applicatives. Une préférence sans conséquence peut garder seulement sa valeur actuelle et un audit léger. Le mécanisme se dimensionne par exposition, fréquence de lecture et besoin de reconstruction.
Erreurs fréquentes d’historisation
Copier toute la ligne à chaque écriture
Cette solution amplifie volume et données sensibles, sans forcément expliquer la cause. Sélectionnez l’unité cohérente et liez les changements à une commande.
Utiliser updated_at comme histoire
Cette date signale seulement la dernière écriture. Elle ne fournit ni ancienne valeur, ni auteur, ni date d’effet. Elle reste utile pour synchroniser, pas pour reconstruire.
Rendre le journal modifiable
Une interface qui réécrit l’audit détruit sa valeur. La correction doit être un nouvel acte relié. Les accès de lecture sont eux-mêmes surveillés pour les données sensibles.
Décision : quel mécanisme choisir
Choisissez un audit pour attribuer des modifications, des versions temporelles pour retrouver une valeur applicable, des événements pour expliquer un processus et reconstruire des projections. Combinez-les seulement si chaque mécanisme répond à une question distincte. Gardez des logs pour l’exécution et des sauvegardes pour la restauration.
Si la valeur détermine argent ou droit, alors conservez période, provenance et motif. En revanche, refusez l’historisation détaillée d’un champ sans usage. À éviter : adopter l’event sourcing uniquement pour obtenir un écran de changements.
- Commencer par les questions et décisions à reconstruire.
- Documenter unité, temps, accès, intégrité et durée.
- Tester correction, purge, projection et restauration.
- Élargir après mesure des lectures et du coût réel.
Plan d’action sur cinq semaines
Semaines un et deux : questions et modèle
Réunissez dix incidents, contestations ou demandes d’audit. Écrivez la question, l’acteur, la conséquence et le délai. Classez les données par sensibilité et durée. Choisissez audit, version ou événement par objet et définissez date d’effet, date de connaissance et correction.
Concevez les lectures, les droits et la purge avant l’écriture. Estimez volume et index. Fermez le contrat des commandes, la provenance et les motifs. Préparez vingt dossiers, dont corrections rétroactives, changements futurs et accès refusés.
Semaines trois à cinq : implémenter et éprouver
Implémentez sur un objet avec écriture atomique, versions et projection courante. Ajoutez métriques, manifestes de purge et alertes. Migrez l’état initial sans inventer de chronologie. Vérifiez la différence et l’état à une date depuis l’interface support.
Provoquez deux écritures concurrentes, événement doublonné, projection en retard, correction rétroactive et purge interrompue. Contrôlez idempotence, absence de trou, masquage et reprise. Restaurez un échantillon puis réappliquez les suppressions nécessaires.
Pilotez avec les personnes qui poseront réellement les questions. Mesurez temps de réponse, volume, accès et anomalies. Étendez si l’histoire est compréhensible et la conservation exécutable ; sinon, réduisez les champs ou simplifiez le mécanisme avant de multiplier les objets.
Le compte rendu vérifie enfin la sortie du mécanisme : export d’un dossier, correction d’une entrée fautive, purge à échéance et retrait d’une projection. Il attribue chaque procédure à une équipe et conserve sa durée. Une fonctionnalité d’historique n’est pas terminée si seules les écritures fonctionnent ; son coût futur se trouve dans les lectures rares, les demandes d’effacement, les changements de schéma et les restaurations après incident.
- Nommer la question et la preuve attendue.
- Choisir le mécanisme et fermer le temps.
- Tester écriture, lecture, correction et purge.
- Mesurer le pilote puis élargir depuis l’usage.
Approfondir modèles et statuts
Gouverner les schémas historiques
Chaque événement ou version publique possède un schéma immuable ou une règle de compatibilité. Les nouveaux lecteurs acceptent les anciennes formes, tandis que les anciennes applications reçoivent seulement ce qu’elles comprennent. Des tests rejouent un échantillon de chaque version. Quand une migration est nécessaire, elle crée une projection nouvelle et conserve la source, afin de pouvoir démontrer la transformation plutôt que d’effacer la forme originale.
Le catalogue relie version, période d’émission, consommateurs et code de projection. Avant de retirer un lecteur, mesurez les entrées encore présentes et les requêtes réglementaires ou support qui pourraient l’utiliser. Une dépendance historique survit parfois longtemps après la fin du flux transactionnel. Lui attribuer une date et un propriétaire évite que la prochaine mise à niveau découvre tardivement un format impossible à interpréter.
Distinguer preuve et analyse
La preuve garde la granularité et l’intégrité nécessaires à un dossier. L’analyse agrège, corrige parfois des dimensions et répond à une population. Construisez l’entrepôt depuis les événements ou versions sans le rendre autorité sur l’histoire transactionnelle. Une correction analytique peut recalculer une série ; elle ne change pas la décision prise à l’époque. Cette séparation permet aux équipes data d’évoluer sans affaiblir la traçabilité métier.
Pour valider cette frontière, choisissez cinq dossiers dont un recalcul analytique a modifié l’indicateur. La vue de preuve doit continuer à montrer la décision originelle, sa règle et les informations disponibles. La vue analytique explique sa correction et sa date de traitement. Un lien contrôlé permet de passer de l’agrégat au dossier sans copier toute la donnée sensible. Ce test protège à la fois la reproductibilité des rapports et la valeur probante de l’historique transactionnel.
Construire un modèle temporel
Le guide sur le modèle de données face aux exceptions complète périodes, absences et migrations.
Relier changements et workflow
Poursuivez avec les statuts métier sans zones grises et l’observabilité des workflows. Appliquez-les à une décision réelle.
- Une question explicite.
- Une temporalité définie.
- Une conservation exécutable.
Conclusion : conserver une preuve utile
Historiser ne consiste pas à stocker chaque ancienne valeur. Le mécanisme utile répond à une question, conserve le bon temps et protège sa provenance. Audit, versions et événements ont des rôles distincts que l’architecture doit assumer.
Les lectures, droits, corrections et purges font partie du produit. Sans elles, l’histoire coûte cher et reste inutilisable. Avec elles, le support et le métier reconstruisent une décision sans fouiller les sauvegardes ni demander une mémoire orale.
Commencez par l’incident que personne ne sait expliquer aujourd’hui. Fermez la preuve nécessaire, implémentez-la sur un objet et mesurez son usage. Cette limite produira un historique plus fiable qu’une copie généralisée.
- Une histoire interprétable.
- Une preuve protégée.
- Une durée maîtrisée.
Dawap peut accompagner cette conception de développement web sur mesure : modèle temporel, audit, événements, sécurité, migration, observabilité et run.