Pour évaluer une base de données, partez des règles dont dépend votre activité et réunissez les preuves que la solution envisagée peut les préserver. Vérifiez séparément la compatibilité des clients, le comportement SQL, les transactions concurrentes et la durabilité. Consignez la version compilée exacte, les paramètres, les résultats observés et les points encore non vérifiés avant d’y confier des données de référence.

Le [rapport de Jepsen sur ParticleDB, publié le 31 octobre](https://jepsen.io/analyses/particledb-1.1.4), illustre l’importance de cette distinction aujourd’hui. L’enquête, financée par Orkes, portait sur les versions allant de 1.1.4 à 1.1.18.11.rc-22, testées sur un seul nœud. Elle a relevé 96 problèmes ; tous, sauf dix, semblaient résolus dans la dernière version compilée testée. Jepsen attribue à Orkes l’annonce de correctifs ultérieurs dans la version 1.1.19-rc.13, tandis que [l’article d’Orkes du 30 octobre](https://orkes.io/blog/particledb-database-built-for-ai-agents) les annonce à partir de la version 1.1.19. Ces versions plus récentes ne faisaient pas partie des tests publiés par Jepsen.

Pour votre évaluation, demandez-vous ce qu’un résultat permet d’établir pour l’application. Le cadre ci-dessous est une méthode proposée, pas un test de base de données que nous aurions réalisé.

## Partez d’une règle métier

Décrivez une propriété qui doit rester vraie lorsque des requêtes se chevauchent ou qu’un processus s’arrête. Cette exigence de départ est souvent appelée un invariant.

Pour un service de réservation, le nombre de réservations confirmées ne doit pas dépasser la capacité. Dans un grand livre comptable, un transfert ne doit pas laisser une seule de ses deux écritures validée. Choisissez les règles propres à l’application, y compris ce que l’utilisateur peut voir après une réussite ou un échec.

Précisez où chaque règle est appliquée : contrainte de base de données, transaction, code applicatif ou système externe. Une base de données ne peut pas préserver une règle que votre implémentation n’exprime jamais. Cette précision aide aussi à examiner une défaillance sans en attribuer immédiatement la cause au moteur de stockage.

## Conservez des preuves distinctes pour chaque couche

Utilisez ce tableau pour préparer l’évaluation. Chaque ligne répond à une question différente ; une réussite sur l’une ne répond pas aux autres.

| Couche | Preuves à réunir | Ce qui reste à établir |
| --- | --- | --- |
| Compatibilité du protocole et des API | Opérations réelles du pilote et du gestionnaire de connexions, requêtes préparées, types renvoyés et gestion des erreurs | Exactitude des résultats SQL ou garanties des transactions |
| SQL et contraintes | Requêtes représentatives et écritures volontairement invalides, avec les résultats attendus et le moment de vérification des contraintes | Comportement lorsque des transactions se chevauchent |
| Concurrence des transactions | Opérations simultanées confrontées au niveau d’isolation documenté et à la règle métier | Conservation des écritures confirmées après une défaillance |
| Durabilité et reprise | Transactions dont la validation a été confirmée et qui subsistent après les défaillances précises du test | Comportement en cas de coupure de courant ou de réplication non couvert par ce test |
| Version et configuration | Empreinte de la version compilée ou de l’image, version du pilote, schéma, paramètres, topologie et révision du test | Comportement équivalent avec une autre version compilée ou un autre déploiement |
| Vérifications en suspens | Exigences non testées, correctifs annoncés, responsable du nouveau test et conséquence sur l’adoption | Validation d’une exigence pour laquelle les preuves manquent encore |

Pour chaque résultat, conservez l’état initial, les opérations, le résultat attendu et le résultat observé. Gardez suffisamment de journaux ou d’historique des transactions pour qu’un autre ingénieur puisse discuter votre interprétation. Un tableau de bord au vert est moins utile si personne ne sait ce que la suite de tests a réellement vérifié.

## Vérifiez la compatibilité PostgreSQL avec les opérations de votre application

Définissez la compatibilité par un ensemble d’exigences. La [documentation du protocole](https://www.postgresql.org/docs/18/protocol.html) PostgreSQL décrit les messages échangés entre clients et serveurs. Réussir une connexion par ce protocole ne répond qu’à une partie des besoins de l’application.

Testez les fonctions du pilote que vous utiliserez, puis vérifiez les fonctionnalités SQL qu’elles sollicitent. Incluez les contraintes, les valeurs nulles, les limites numériques et la gestion des erreurs lorsqu’elles influent sur vos règles. Exécutez les requêtes réelles de l’application, y compris les opérations moins fréquentes, comme un export administratif.

Si vous comparez les résultats avec PostgreSQL, définissez d’abord les différences acceptables. Des lignes non triées ne sont pas tenues d’arriver dans le même ordre. La précision numérique, le moment de vérification des contraintes et l’ordre de priorité des erreurs nécessitent leurs propres exigences. Évaluez chaque différence au regard des garanties documentées et des besoins applicatifs, sans considérer tout écart comme un défaut.

## Examinez une règle de capacité sur un exemple

Prenons un **atelier fictif de 30 places, avec 29 réservations confirmées**. Chaque transaction de réservation compte les réservations confirmées, en ajoute une seulement s’il reste de la place, puis valide la transaction. Cet exemple est synthétique ; nous ne l’avons exécuté sur aucune base de données.

Prévoyez une évaluation avec deux clients distincts :

1. Démarrez les deux transactions ensemble. Si chacune peut compter 29 réservations avant la première insertion, conservez cet historique. Notez les blocages si le moteur sérialise les accès plus tôt.
2. Laissez chaque transaction tenter son insertion conditionnelle, puis sa validation. Consignez séparément les résultats des instructions, les confirmations de validation et les erreurs.
3. Lisez l’état final de référence depuis une nouvelle connexion et vérifiez la règle de capacité.
4. Si une transaction échoue avec une erreur de sérialisation, relancez-la entièrement, avec ses étapes de lecture, de vérification et d’écriture, puis consignez la décision obtenue.

Avec une garantie de sérialisabilité, les transactions validées doivent produire un effet compatible avec une exécution séquentielle. Selon la logique décrite ici, deux nouvelles confirmations portant le total à 31 ne respecteraient pas cette garantie. Une transaction pourrait plutôt échouer, puis constater lors d’une nouvelle tentative que l’atelier est complet.

La [documentation de PostgreSQL sur l’isolation](https://www.postgresql.org/docs/18/transaction-iso.html) explique la sérialisabilité et la nécessité de relancer les transactions entières. Elle précise également que le niveau Repeatable Read peut autoriser des anomalies de sérialisation. Si vous choisissez des garanties plus faibles qui permettent cette interaction, la surréservation révèle une inadéquation avec l’application ; elle ne démontre pas, à elle seule, un bug de la base de données.

Un dépassement de délai côté client doit être consigné comme un résultat distinct. Si la connexion est perdue au moment de la validation, le client peut ignorer si la réservation a été conservée. Levez cette incertitude à l’aide d’un identifiant d’opération stable avant de répéter l’action métier.

Dans ce modèle, stockez l’identifiant et la réservation de façon atomique, imposez l’unicité de l’identifiant et réutilisez-le lors des nouvelles tentatives. L’absence temporaire d’une donnée ne prouve pas, à elle seule, que la transaction dont le délai a expiré a été annulée. Le niveau d’isolation de la base de données ne peut pas empêcher à lui seul l’application d’envoyer deux e-mails de confirmation ou de débiter deux fois le même paiement.

## Précisez les pannes couvertes par les garanties de durabilité

Demandez quelles garanties la base de données offre lorsqu’elle confirme une validation, avec les paramètres que vous comptez déployer. Choisissez ensuite des tests qui vérifient ces engagements.

La [documentation de PostgreSQL sur la validation asynchrone](https://www.postgresql.org/docs/18/wal-async-commit.html) en donne un exemple concret : cette configuration peut confirmer des transactions qui seront ensuite perdues lors d’une panne. C’est un compromis documenté, pas un manquement à la garantie associée à cette configuration.

Dans un environnement d’évaluation isolé, consignez les identifiants des opérations confirmées, provoquez la défaillance choisie et comparez les données après reprise. Distinguez les opérations à l’issue incertaine des transactions dont la validation a été confirmée. Arrêter un processus serveur ne reproduit pas une coupure d’alimentation du stockage, et redémarrer un nœud ne teste pas la bascule vers une réplique. La [documentation de PostgreSQL sur la fiabilité](https://www.postgresql.org/docs/18/wal-reliability.html) explique pourquoi les différentes couches de stockage comptent pour la persistance.

Adaptez les preuves au déploiement envisagé. Si vous avez besoin d’une bascule entre régions, un redémarrage local réussi laisse cette exigence sans réponse.

## Distinguez un correctif annoncé d’un résultat vérifié

L’annonce d’un correctif par un fournisseur est une information utile. Conservez avec le résultat le nom de celui qui l’annonce et la version précise, jusqu’à ce que le comportement requis ait été vérifié de nouveau.

Consignez le cas de reproduction qui a été relancé, l’exécution éventuelle de la charge de travail environnante et les changements de version compilée ou de configuration. Distinguez les états **réussite observée**, **échec observé**, **correctif annoncé par le fournisseur, en attente d’un nouveau test** et **non testé**. La réussite d’un cas de reproduction ne prouve pas que tous les cas voisins sont couverts ; celle d’une suite plus étendue ne prouve pas que le système est correct dans toutes les situations.

Faites en sorte que les preuves manquantes aient une conséquence sur la décision. Supposons que la solution envisagée réussisse vos vérifications SQL, mais que vous manquiez de preuves sur la conservation des écritures confirmées lors d’une bascule dans le déploiement requis. Si cette conservation est impérative, gardez les réservations de référence dans le stockage existant. Vous pouvez néanmoins évaluer la nouvelle solution pour un index de recherche reconstructible, avec ses propres exigences. Ne noyez pas l’exigence non vérifiée dans une note globale pour approuver les deux usages.

## Rédigez une décision qu’un autre ingénieur pourra examiner

Terminez par l’usage envisagé, les garanties requises, le déploiement exact évalué, les liens vers les preuves et les exigences en suspens. Indiquez qui accepte chaque risque résiduel et quelles nouvelles preuves modifieraient la décision. Consignez les résultats de performance avec la même configuration pour que les comparaisons de vitesse restent pertinentes.

Si vous approuvez ensuite une migration, notre [article sur la migration depuis Deno Deploy](/blog/deno-deploy-shutdown-migration-tests) traite du travail distinct de test de la destination et de préparation de la bascule. La décision examinée ici intervient avant : cette base de données dispose-t-elle de preuves suffisantes pour cet usage dans l’application ? Partez de la règle que vous ne pouvez pas vous permettre de violer et laissez la décision d’adoption en suspens tant que les preuves exigées ne sont pas réunies.