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, pas UnprocessedKeys. Le côté lecture utilise l'autre nom, et en JavaScript une faute de frappe ici compile, se lit comme undefined, et transforme le do/while en 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 WriteRequest a exactement deux membres optionnels, PutRequest et DeleteRequest, et aucun n'accepte ConditionExpression ni ReturnValues. 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èvent ValidationException / Too many items requested for the BatchWriteItem call. Toucher deux fois la même clé lève Provided 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 PutItem ou un DeleteItem individuel, 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

Références

Dernière vérification le 2026-07-28 par rapport à la documentation officielle AWS liée ci-dessus.

Travaille avec DynamoDB sans la Console

Un client de bureau rapide pour DynamoDB qui exécute le vrai SQL que DynamoDB ne peut pas — JOINs, GROUP BY, agrégations — avec édition visuelle et un agent IA sur tes propres clés Bedrock.

Essai gratuit de 30 jours, sans carte bancaire — ensuite la formule Gratuit, sans limite de durée.