DynamoDB BatchWriteItem en Node.js (AWS SDK v3)
BatchWriteItem écrit ou supprime jusqu'à 25 éléments en une seule requête. Ce n'est pas un UpdateItem en plus petit : chaque PutRequest remplace l'élément stocké en entier, et les types v3 ne te laissent nulle part où accrocher une condition. Les opérations par lot dans DynamoDB couvrent les limites et le modèle d'échec partiel ; cette page porte sur l'appel v3 et sur la seule façon dont il perd des données en silence.
Code
import {BatchWriteItemCommand, DynamoDBClient} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
let requestItems = {
Music: [
{
PutRequest: {
Item: {
Artist: {S: 'Arturo Sandoval'},
SongTitle: {S: 'Cubano Chant'},
AlbumTitle: {S: 'Danzon'},
Year: {N: '1994'}
}
}
},
{
PutRequest: {
Item: {
Artist: {S: 'Arturo Sandoval'},
SongTitle: {S: 'A Mis Abuelos'},
AlbumTitle: {S: 'Danzon'},
Year: {N: '1994'}
}
}
},
{
DeleteRequest: {
Key: {Artist: {S: 'Ella Fitzgerald'}, SongTitle: {S: 'Misty'}}
}
}
]
};
let attempt = 0;
do {
const response = await client.send(new BatchWriteItemCommand({RequestItems: requestItems}));
// Writes that were throttled come back in UnprocessedItems — resubmit them
// with exponential backoff until the map is empty.
requestItems = response.UnprocessedItems;
if (requestItems && Object.keys(requestItems).length > 0) {
attempt += 1;
await sleep(Math.min(100 * 2 ** attempt, 5000));
}
} while (requestItems && Object.keys(requestItems).length > 0);
console.log('Batch written');Explication
- Le membre résiduel s'appelle
UnprocessedItems, pasUnprocessedKeys. Le côté lecture utilise l'autre nom, et en JavaScript une faute de frappe ici compile, se lit commeundefined, et transforme ledo/whileen un appel unique qui laisse tomber les écritures throttlées. TypeScript l'attrape ; le JS pur, non. - Il n'y a nulle part où mettre une condition. Le type v3
WriteRequesta exactement deux membres optionnels,PutRequestetDeleteRequest, et aucun n'accepteConditionExpressionniReturnValues. Ce n'est pas le SDK qui joue la prudence : la référence de l'API dit qu'on ne peut pas spécifier de conditions sur les requêtes put et delete individuelles. Si une écriture a besoin d'une garde, elle n'a pas sa place dans un lot, elle a sa place dans un UpdateItem avec condition ou dans une transaction. - Deux erreurs attrapables, toutes deux non réessayables, distinguées sur
err.name. Vingt-six entrées lèventValidationException/Too many items requested for the BatchWriteItem call. Toucher deux fois la même clé lèveProvided list of item keys contains duplicates, et ce message couvre aussi bien une paire put+delete que deux puts, ce qui surprend la première fois. - La liste des rejets du lot entier est plus longue que les trois évidents. À côté de plus de 25 requêtes, d'un élément de plus de 400 Ko et d'un total de plus de 16 Mo, DynamoDB refuse le lot pour une table absente, une clé qui ne correspond pas au schéma, une clé de partition de plus de 2 048 octets ou une clé de tri de plus de 1 024 octets. Une seule mauvaise entrée te coûte les 25.
- Le lot t'achète des allers-retours, pas de la capacité. Chaque entrée est facturée comme un
PutItemou unDeleteItemindividuel, arrondi au Ko supérieur, et une suppression visant un élément inexistant consomme quand même une unité d'écriture.
Un PutRequest réduit aux clés détruit le reste de l'élément
Ella Fitzgerald / Misty part avec un AlbumTitle et un Year. Envoie un seul PutRequest ne portant que les deux attributs de clé :
{PutRequest: {Item: {Artist: {S: 'Ella Fitzgerald'}, SongTitle: {S: 'Misty'}}}}Puis relis-le avec ConsistentRead: true. DynamoDB Local 3.3.0 renvoie :
{
"Artist": { "S": "Ella Fitzgerald" },
"SongTitle": { "S": "Misty" }
}AlbumTitle et Year ont disparu. L'appel a réussi, UnprocessedItems valait {}, et rien dans la réponse ne mentionne les deux attributs qu'il a laissés tomber. Un put est un remplacement d'élément entier : un lot assemblé à partir d'une charge partielle (un corps de requête API, un sous-ensemble de colonnes CSV, un résultat de Query projeté qui omettait des attributs) efface tous les attributs que la charge ne portait pas.
C'est le mode d'échec à anticiper quand tu utilises un lot pour ce qui ressemble à une mise à jour. La correction consiste à relire l'élément courant et à fusionner, ou à arrêter de grouper et à passer à UpdateItem, qui ne touche que les attributs que tu nommes.
L'autre raison pour laquelle un lot de 25 éléments devient un lot de 12, c'est la taille. Les écritures sont arrondies au Ko supérieur pour la facturation et la requête plafonne à 16 Mo, donc le vrai nombre d'octets d'un élément décide à la fois de ta facture et du nombre qui tient. Le calculateur de taille d'élément te donne ce chiffre par élément avant que tu n'assembles le tableau.
Pour charger, modifier et supprimer des éléments en masse sans écrire à la main la sémantique de remplacement, télécharge DynoTable.
Exemples liés
- Écriture par lot DynamoDB en Python — le
batch_writer()de boto3 fait la boucle de reprise à ta place. - DynamoDB BatchWriteItem avec l'AWS CLI — la même écriture par lot depuis le shell.
- DynamoDB TransactWriteItems en Node.js — quand les écritures doivent réussir ou échouer ensemble.
- Les opérations par lot dans DynamoDB — limites, échec partiel, et quand le lot est rentable.
- "Too many items requested for the BatchWriteItem call" — plus de 25 requêtes put/delete dans un seul lot.
- "Provided list of item keys contains duplicates" — deux requêtes touchant la même clé dans un lot.
Références
- BatchWriteItem — Amazon DynamoDB API Reference
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
Dernière vérification le 2026-07-28 par rapport à la documentation officielle AWS liée ci-dessus.