Choisissez DynamoDB quand vous pouvez lister vos modèles d'accès à l'avance et que votre trafic est irrégulier : il parle HTTP et monte donc en charge avec la concurrence Lambda, par conception. Choisissez RDS (PostgreSQL ou Aurora) quand il vous faut des requêtes ad hoc, des jointures et des invariants multi-lignes, en acceptant que Lambda exige RDS Proxy devant la base. Beaucoup de plateformes finissent par exploiter les deux, et c'est une architecture légitime, pas un échec. Ce guide passe en revue les critères qui tranchent vraiment.
Connaissez-vous vos modèles d'accès à l'avance ?
C'est la première question, parce que DynamoDB la rend non négociable : la table se conçoit autour des requêtes que vous exécuterez, avant d'écrire le code. Si vous savez les énumérer (une commande par identifiant, les commandes d'un client, les plus récentes d'abord), DynamoDB les servira en quelques millisecondes. Sinon, un schéma relationnel reste le choix prudent.
Les recommandations de conception NoSQL d'AWS sont explicites : modélisez la table d'après les modèles d'accès de l'application, pas d'après les entités. Le SQL fait le pari inverse. Un schéma normalisé répond aux questions que personne n'avait anticipées : le filtre marketing, l'export comptable, la jointure demandée un vendredi. Les outils de reporting et de back-office parlent SQL nativement ; presque aucun ne parle DynamoDB.
En quoi le modèle de connexion de Lambda change-t-il le choix ?
Radicalement, et c'est le critère que les équipes découvrent en production. DynamoDB est une API HTTP : chaque environnement d'exécution Lambda envoie des requêtes sans état, donc 5 ou 5 000 invocations concurrentes se ressemblent. PostgreSQL maintient des connexions TCP avec état, et chaque environnement Lambda ouvre la sienne, ce qui le tue précisément sous la charge.
Un pic de trafic crée des centaines d'environnements, chacun avec sa connexion ; Postgres refuse les nouvelles une fois max_connections atteint, et le backend échoue alors que la base reste presque inactive. RDS Proxy corrige cela en possédant un pool chaud et en multiplexant les requêtes Lambda sur bien moins de connexions réelles. Ce n'est pas optionnel à l'échelle : comptez-le comme une partie de la facture RDS. Le même raisonnement vaut pour toute ressource mutualisée, comme nous le détaillons dans Lambda ou serveurs.
Les modèles de requête diffèrent autant que les modèles de connexion :
// DynamoDB : dernières commandes d'un client (DocumentClient, SDK v3)
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, QueryCommand } from '@aws-sdk/lib-dynamodb';
const doc = DynamoDBDocumentClient.from(new DynamoDBClient({}));
const { Items } = await doc.send(new QueryCommand({
TableName: 'orders',
KeyConditionExpression: 'customerId = :c',
ExpressionAttributeValues: { ':c': 'cus_123' },
ScanIndexForward: false, // les plus récentes d'abord
Limit: 20,
}));
// PostgreSQL via RDS Proxy : même intention, plus une jointure impossible en DynamoDB
import { Pool } from 'pg';
// Un pool par environnement d'exécution, créé hors du handler
const pool = new Pool({ host: process.env.PROXY_ENDPOINT, max: 1 });
const { rows } = await pool.query(
`SELECT o.id, o.total, c.email
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.customer_id = $1
ORDER BY o.created_at DESC
LIMIT 20`,
['cus_123'],
);
Comment se comparent montée en charge et exploitation en 2026 ?
Les deux options sont crédibles en 2026, mais elles montent en charge selon des axes différents. Le mode on-demand de DynamoDB absorbe le trafic de zéro aux pics extrêmes sans planification de capacité, avec une surface opérationnelle proche de zéro. Aurora Serverless v2 ajuste le calcul par paliers fins, rapidement, mais il fait grandir une instance de base, pas des requêtes individuelles.
La charge d'exploitation suit la même ligne de partage. Avec DynamoDB, vous réglez des clés et surveillez les métriques de throttling ; pas de moteur à patcher, pas de vacuum à planifier, pas d'exercice de bascule. Avec Aurora, vous gardez les versions du moteur, les groupes de paramètres, les limites de connexions et la santé des index, même en serverless. Aucun des deux fardeaux n'est énorme ; ce sont simplement des métiers différents.
Vous hésitez sur la base que vos modèles d'accès désignent vraiment ? Décrivez votre système : diagnostic d'une page sous 48 h.
Recevoir mon diagnostic →Qui gagne sur les transactions et les invariants multi-lignes ?
Le relationnel, et largement, dès que les invariants couvrent plusieurs lignes. DynamoDB propose bien des transactions ACID : TransactWriteItems groupe jusqu'à 100 éléments entre tables, tout ou rien. Mais pas de transactions interactives, pas de clés étrangères, pas de contraintes appliquées par le moteur : votre code applicatif porte les invariants.
Si le cœur de votre domaine touche aux mouvements d'argent, à un stock qui ne doit jamais passer en négatif ou à tout ce qu'un auditeur lira, les contraintes de PostgreSQL, l'isolation sérialisable et l'outillage mature pèsent lourd. Si vos écritures sont surtout des événements indépendants rattachés à une entité, les écritures conditionnelles de DynamoDB couvrent l'essentiel.
Quelle est la forme de votre courbe de coûts ?
Ignorez les prix absolus et regardez la forme. DynamoDB on-demand facture à la requête : le coût suit l'usage exactement, donc un trafic en pics à moyenne basse coûte peu, et l'inactivité presque rien au-delà du stockage. RDS facture la capacité provisionnée à l'heure : une instance stable et bien utilisée est efficiente, une instance inactive est du gaspillage pur.
Le croisement joue dans les deux sens. Une table sollicitée en continu à volume élevé et prévisible peut coûter plus cher qu'une instance bien dimensionnée faisant le même travail (la capacité provisionnée réduit l'écart). Aurora Serverless v2 atténue le problème de l'inactivité mais conserve une courbe en forme d'instance. Modélisez votre histogramme de trafic réel avant de croire l'une ou l'autre intuition.
Combien coûte un changement d'avis plus tard ?
Cher, dans les deux sens, et c'est pourquoi cette décision mérite mieux qu'un réflexe. Une conception single-table DynamoDB encode vos modèles d'accès dans la structure des clés ; un nouveau besoin signifie de nouveaux GSI au mieux, une refonte de table avec backfill au pire. Quitter le SQL impose de réécrire chaque jointure et chaque contrainte dont votre code dépend en silence.
Les migrations de schéma sur une base relationnelle sont routinières et bien outillées ; migrer une table vivante d'une famille de bases vers l'autre est un projet qui se compte en mois. Notre règle : ne choisir DynamoDB que si les modèles d'accès semblent stables, et garder une couche repository entre les handlers et la base pour qu'un futur déménagement reste survivable.
La réponse honnête, n'est-ce pas les deux ?
Souvent, oui. Le motif vers lequel beaucoup de plateformes convergent : DynamoDB pour les données chaudes d'événements et d'état (sessions, commandes en cours, état d'équipements), PostgreSQL pour le reporting relationnel et le back-office, avec des événements pour synchroniser l'un vers l'autre. Chaque base fait le travail pour lequel elle est conçue, sans être forcée dans le rôle de l'autre.
DynamoDB Streams ou des événements métier via EventBridge alimentent Postgres de façon asynchrone ; le reporting tolère quelques secondes de retard, et le chemin chaud n'attend jamais une jointure. Nous avons décrit cette plomberie dans notre guide du pattern EventBridge, SQS et Lambda. Le prix : une cohérence à terme entre les deux bases et un pipeline de plus à surveiller. Ne le payez que si les deux charges existent vraiment.
DynamoDB ou RDS : le tableau récapitulatif
Le tableau ci-dessous condense les critères. Lisez-le ligne par ligne face à votre charge réelle, pas comme un score : une ligne décisive (des modèles d'accès imprévisibles, par exemple) pèse plus que trois lignes confortables. D'expérience, le modèle de connexion et la forme des coûts sont les lignes que les équipes jugent mal le plus souvent.
| Critère | DynamoDB | RDS (+Proxy) / Aurora |
|---|---|---|
| Modèles d'accès | Connus à l'avance, encodés dans les clés | Requêtes ad hoc, jointures, besoins évolutifs |
| Connexions Lambda | HTTP sans état, suit la concurrence | TCP mutualisé via RDS Proxy, indispensable à l'échelle |
| Montée en charge | À la requête, on-demand jusqu'aux pics extrêmes | Par instance ; Aurora Serverless v2 ajuste le calcul vite |
| Transactions | TransactWriteItems, 100 éléments max, pas d'interactif | ACID complet, contraintes, isolation sérialisable |
| Reporting | Faible : exporter ou synchroniser ailleurs | SQL natif, tous les outils BI le parlent |
| Forme des coûts | À la requête : aime les pics à moyenne basse | À l'heure d'instance : aime la charge stable et élevée |
| Charge d'exploitation | Quasi nulle : clés et métriques de throttling | Versions moteur, paramètres, index, exercices de bascule |
La checklist de décision
Avant de vous engager dans un sens ou dans l'autre, posez ceci sur papier :
- Listez chaque modèle d'accès ; si la liste ne restera pas stable, penchez SQL.
- Recensez comment le back-office et la finance interrogeront les données ; ce travail finit en SQL de toute façon.
- Esquissez votre histogramme de trafic : pics à moyenne basse pour DynamoDB, charge stable et élevée pour les instances.
- Si Lambda parle à RDS, budgétez RDS Proxy dès le premier jour.
- Écrivez les invariants qui couvrent plusieurs lignes ; s'ils sont au cœur du domaine, favorisez le relationnel.
- Gardez une couche repository pour que le choix reste réversible côté code.
- Étudiez l'hybride avant de forcer une base dans le rôle de l'autre.