BatchWriteItem do DynamoDB em Node.js (AWS SDK v3)
O BatchWriteItem grava ou apaga até 25 itens em uma requisição. Ele não é um UpdateItem menor: todo PutRequest substitui o item armazenado inteiro, e os tipos da v3 não te dão onde anexar uma condição. Operações em lote no DynamoDB cobre os limites e o modelo de falha parcial; esta página é sobre a chamada v3 e sobre a única forma pela qual ela perde dados silenciosamente.
Código
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');Explicação
- O campo dos restos é
UnprocessedItems, nãoUnprocessedKeys. O lado da leitura usa o outro nome, e em JavaScript um erro de digitação aqui compila, é lido comoundefinede transforma odo/whileem uma chamada de passagem única que joga fora as escritas com throttle. O TypeScript pega isso; o JS puro não. - Não há onde colocar uma condição. O tipo
WriteRequestda v3 tem exatamente dois campos opcionais,PutRequesteDeleteRequest, e nenhum aceitaConditionExpressionnemReturnValues. Não é o SDK sendo conservador: a referência da API diz que você não pode especificar condições em requisições individuais de put e delete. Se uma escrita precisa de uma guarda, ela não pertence a um lote — pertence a um UpdateItem com condição ou a uma transação. - Dois erros passíveis de
catch, ambos não retentáveis, discriminados porerr.name. Vinte e seis entradas geramValidationException/Too many items requested for the BatchWriteItem call. Tocar a mesma chave duas vezes geraProvided list of item keys contains duplicates, e essa mensagem cobre tanto um par put+delete quanto dois puts, o que soa estranho na primeira vez que você a vê. - A lista de rejeições do lote inteiro é maior que as três óbvias. Além de mais de 25 requisições, um item acima de 400 KB e um total acima de 16 MB, o DynamoDB recusa o lote por tabela inexistente, por uma chave que não corresponde ao schema, por uma chave de partição acima de 2048 bytes ou por uma chave de classificação acima de 1024 bytes. Uma entrada ruim te custa as 25.
- Agrupar em lote compra idas e voltas, não capacidade. Cada entrada é cobrada como um
PutItemouDeleteItemindividual, arredondado para cima a cada 1 KB, e um delete mirado em um item inexistente ainda consome uma unidade de escrita.
Um PutRequest só com a chave destrói o resto do item
Ella Fitzgerald / Misty começa com um AlbumTitle e um Year. Envie um PutRequest levando apenas os dois atributos de chave:
{PutRequest: {Item: {Artist: {S: 'Ella Fitzgerald'}, SongTitle: {S: 'Misty'}}}}Depois leia de volta com ConsistentRead: true. O DynamoDB Local 3.3.0 retorna:
{
"Artist": { "S": "Ella Fitzgerald" },
"SongTitle": { "S": "Misty" }
}AlbumTitle e Year sumiram. A chamada teve sucesso, UnprocessedItems veio {} e nada na resposta menciona os dois atributos que ela descartou. Um put é uma substituição do item inteiro, então um lote montado a partir de um payload parcial (o corpo de uma requisição de API, um subconjunto de colunas de CSV, o resultado de um Query projetado que omitiu atributos) apaga todo atributo que o payload não carregava.
Esse é o modo de falha a prever quando você usa um lote para o que parece uma atualização. A correção é ler o item atual primeiro e mesclar, ou parar de usar lote e usar UpdateItem, que toca apenas os atributos que você nomear.
O outro motivo pelo qual um lote de 25 itens vira um lote de 12 é o tamanho. As escritas arredondam para cima a cada 1 KB na cobrança e a requisição tem teto de 16 MB, então a contagem real de bytes de um item decide tanto a sua conta quanto quantos cabem. A calculadora de tamanho de item te dá esse número por item antes de você montar o array.
Para carregar, editar e apagar itens em massa sem escrever à mão a semântica de substituição, baixe o DynoTable.
Exemplos relacionados
- Escrita em lote no DynamoDB em Python — o
batch_writer()do boto3 faz o laço de retry por você. - BatchWriteItem do DynamoDB com a AWS CLI — a mesma escrita em lote a partir do shell.
- TransactWriteItems do DynamoDB em Node.js — quando as escritas precisam ter sucesso ou falhar juntas.
- Operações em lote no DynamoDB — limites, falha parcial e quando o lote compensa.
- "Too many items requested for the BatchWriteItem call" — mais de 25 requisições de put/delete em um lote.
- "Provided list of item keys contains duplicates" — duas requisições tocando a mesma chave em um lote.
Referências
- 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
Verificado pela última vez em 2026-07-28 contra a documentação oficial da AWS vinculada acima.