Le débat DynamoDB contre Postgres se mène généralement comme une religion. Un camp dit que les données relationnelles appartiennent à une base relationnelle et que la conception single-table est un casse-tête qu'on résout une fois et qu'on regrette pour toujours. L'autre camp dit que Postgres ne monte pas en charge sans gardien et que DynamoDB est le seul magasin qui vous laisse cesser de penser à la capacité. Les deux ont raison sur les cas qu'ils ont en tête et tort de croire qu'il existe une seule réponse.
Nous exploitons les deux, sur la même plateforme, pour un client américain. Six tables DynamoDB et un cluster Aurora Serverless v2 Postgres, choisis workload par workload. Voici la règle que nous utilisons, les quatre workloads qu'elle a produits, celui que nous avons mis dans le mauvais magasin et déplacé, et le coût de chaque côté.
La règle
Posez deux questions sur le workload, et la réponse tombe d'elle-même.
1. Connaissez-vous les schémas d'accès, et y en a-t-il moins d'une dizaine ? DynamoDB est un magasin clé-valeur avec des index secondaires. Vous concevez la table autour des requêtes. Si les requêtes sont connues et peu nombreuses, cette conception est un après-midi agréable et la table les servira à n'importe quelle échelle pour un coût fixe faible par requête. Si les requêtes sont inconnues, évolutives ou ad hoc (un administrateur qui a besoin de « toutes les commandes des clients du Texas qui ont acheté le produit X en mars »), chaque nouvelle question est un nouvel index ou un scan, et vous construirez une seconde copie des données quelque part de requêtable dans l'année.
2. Avez-vous besoin de transactions sur de nombreuses lignes, de jointures ou d'agrégats ? DynamoDB a des transactions, jusqu'à 100 éléments. Il n'a ni jointures ni GROUP BY. Si le workload est « sommer le chiffre d'affaires par produit par semaine », ou « mettre à jour la commande, le stock et le grand livre atomiquement », Postgres le fait en une instruction et DynamoDB le fait en code applicatif que vous écrirez subtilement faux au moins une fois.
Schémas d'accès connus et peu nombreux, pas de jointures ni d'agrégats : DynamoDB. Tout le reste : Postgres. En cas d'égalité, Postgres, parce que le coût de l'erreur est asymétrique : une table Postgres qui se révèle avoir un schéma clé-valeur chaud peut recevoir un index ou un cache ; une table DynamoDB qui se révèle avoir besoin de jointures a besoin d'une migration.
Les quatre workloads
Sessions et seaux de limitation de débit → DynamoDB. Un schéma d'accès chacun : lire par clé, écrire par clé, expirer par TTL. Des millions de petits éléments, un trafic en pics, aucun intérêt à les interroger jamais autrement que par la clé. C'est le workload DynamoDB du manuel et il coûte environ 4 $ par mois à notre volume, à la demande, sans capacité à laquelle penser. Les mettre dans Postgres reviendrait à une table qui représente 90 % du volume d'écriture pour 0 % de la valeur métier, et un job de vacuum pour l'empêcher de gonfler.
Catalogue produit et configuration par tenant → DynamoDB, single-table. Sept schémas d'accès, tous connus : produit par id, produits par tenant, produits par tenant et catégorie, config par tenant, quelques autres. Beaucoup de lectures, peu d'écritures, et la forme d'un produit est un document, pas un ensemble de lignes jointes. Une table avec une clé composite et deux GSI sert les sept. L'exercice de restauration a montré le piège de la perte des réglages, mais la table elle-même n'a jamais eu besoin d'un changement en dix-huit mois.
Commandes, paiements, grand livre → Postgres. C'est le workload où la seconde question dit non. Une commande touche la commande, ses lignes, la réservation de stock et l'écriture au grand livre dans une seule transaction ; la finance veut le chiffre d'affaires par produit par région par semaine ; le support veut « chaque commande de ce client avec un remboursement dans les 90 derniers jours ». Jointures, agrégats, questions ad hoc, et une forte préférence pour les invariants que donnent les clés étrangères et les contraintes. Aurora Serverless v2 à 0,5 ACU minimum, passé en revue séparément.
Journal d'événements pour l'index de recherche → DynamoDB avec Streams. Ajout seul, lu uniquement par le consommateur du stream, expiration après 30 jours. Schéma connu, pas de jointures, et Streams donne le flux de changements gratuitement.
Celui que nous avons raté
Les profils clients ont commencé dans DynamoDB. Les schémas d'accès semblaient connus : profil par id, profil par email, profils par tenant. Trois schémas, une forme de document, adéquation évidente.
Puis le produit a grandi. Le support voulait les clients par date d'inscription. Le marketing voulait les clients qui n'avaient pas commandé depuis 60 jours, ce qui est une jointure avec les commandes. La finance voulait la valeur vie client, un agrégat. Chaque demande est devenue soit un nouveau GSI (nous en avons ajouté trois), soit un scan avec filtre qui prenait des minutes et coûtait de vrais euros, soit un export nocturne vers Postgres qui était périmé au matin. À la quatrième demande, nous avions deux copies des données clients, dont l'une toujours légèrement fausse.
Nous avons déplacé les profils vers Postgres. La migration a pris une semaine : double écriture pendant quelques jours, backfill, bascule des lectures, suppression des écritures DynamoDB, suppression de la table un mois plus tard. Les trois GSI ont disparu. L'export nocturne a disparu. Chaque question posée sur les clients depuis a été une requête, pas un projet.
La leçon est dans la première question. « Schémas d'accès connus » veut dire connus pour la durée de vie des données, pas connus aujourd'hui. Les profils sont l'entité que tout le monde dans l'entreprise finit par vouloir découper autrement. Les sessions, non. Le magasin doit suivre ça.
Ce que coûte chaque côté, honnêtement
| DynamoDB (4 tables) | Aurora Serverless v2 Postgres | |
|---|---|---|
| Facture mensuelle | ~13 $ à la demande | ~45 $ au plancher de 0,5 ACU, plus sous charge |
| Planification de capacité | Aucune | Fixer les ACU min et max ; le plancher est la facture |
| Changements de schéma | Gratuits pour les attributs ; un nouveau schéma d'accès est un nouveau GSI, avec backfill | ALTER TABLE, migrations, parfois un verrou à anticiper |
| Sauvegardes | PITR activé, la restauration perd les réglages | PITR activé, la restauration est un nouveau cluster |
| Questions ad hoc | Scan, ou export ailleurs | Une requête |
| Surprises opérationnelles en 18 mois | Une : partition chaude sur une clé de tenant mal choisie, corrigée avec un suffixe | Une : une longue transaction a tenu un verrou pendant une migration |
| Ce que vous ne pouvez pas faire | Jointures, agrégats, requêtes imprévues | Cesser complètement d'y penser |
Le côté DynamoDB est moins cher et plus calme pour ce qu'il sait faire. Le côté Postgres coûte plus et répond à plus. Aucun des chiffres n'est l'argument ; le workload l'est.
La version courte
Par workload, deux questions : les schémas d'accès sont-ils connus et peu nombreux, pour la durée de vie des données ; et faut-il des jointures, des agrégats ou des transactions larges. Oui et non veut dire DynamoDB. Tout le reste veut dire Postgres. Attendez-vous à en rater un, et attendez-vous à ce que le raté soit l'entité que tout le monde dans l'entreprise finit par vouloir découper autrement.
Si vous choisissez un magasin pour une nouvelle plateforme, ou si vous avez une table DynamoDB avec son quatrième GSI et un export nocturne, nous pouvons vous aider à trier les workloads. C'est une séance au tableau blanc, pas une religion.