Avançado6 min de leitura

Adaptive Capacity no DynamoDB: o que faz e o que não faz

O DynamoDB espalha sua tabela por partições, mas seu tráfego raramente se espalha por igual. Burst capacity e adaptive capacity são os dois mecanismos automáticos que impedem uma carga de trabalho desequilibrada de ser limitada (throttling) — até ela bater num limite rígido.

O que é adaptive capacity no DynamoDB?

Adaptive capacity no DynamoDB é um mecanismo automático que desloca throughput não usado em direção a uma para que uma chave desequilibrada não sofra throttling enquanto o resto da tabela fica ocioso. Combinado com burst capacity, ele absorve picos e desequilíbrio sustentado de graça — mas não consegue empurrar uma única chave além do teto da partição.

  • Burst capacity te empresta até 5 minutos (300 segundos) de throughput não usado para atravessar picos curtos. É um buffer, não um recurso que você ajusta.
  • Adaptive capacity automaticamente eleva o throughput para uma — puxando do restante da capacidade não usada da sua tabela — para que uma chave desequilibrada não sofra throttling.
  • Ela até isola um item quente em sua própria partição, dando a uma única chave até o teto da partição de 3.000 RCU / 1.000 WCU.
  • Não é licença para ignorar o design de chaves. Além do teto por partição não sobra de onde emprestar — uma chave genuinamente quente ainda sofre throttling.

Conheça primeiro o teto da partição

Toda partição é limitada de forma independente: 3.000 unidades de leitura e 1.000 unidades de gravação por segundo. Esse limite é físico, não provisionado — ele vale tanto em tabelas provisionadas quanto sob demanda. (AWS, Burst and adaptive capacity.)

Vindo do SQL, você raciocina sobre a carga total do servidor. No DynamoDB a unidade que sofre throttling é a partição única, e uma chave desequilibrada pode derreter enquanto a tabela fica 90% ociosa. Essa é a lacuna que ambos os mecanismos existem para fechar.

Burst capacity absorve o pico curto

Sempre que você não usa totalmente o throughput de uma partição, o DynamoDB guarda o que sobra. Até 300 segundos dessa capacidade não usada ficam em reserva, e um pico repentino pode drená-la mais rápido do que sua taxa por segundo normalmente permitiria.

É invisível e automático. Você não consegue dimensioná-la, e o DynamoDB pode silenciosamente gastar parte dela no seu próprio trabalho de fundo. Trate-a como um amortecedor para tráfego em rajadas — nunca como folga com a qual você possa contar no planejamento.

Adaptive capacity turbina a partição quente

Burst capacity lida com picos curtos. Adaptive capacity lida com desequilíbrio sustentado. Quando uma partição fica quente enquanto suas vizinhas ficam ociosas, o DynamoDB desloca throughput em direção à quente — até o total da tabela e o teto da partição.

Digamos que você rode uma tabela de telemetria de frota com chave VEHICLE#<id> (partição) e TS#<epoch> (ordenação). Uma van de entrega numa zona de flash-sale emite 10× os pings de qualquer outra. Sua partição está quente; as partições das outras 200 vans ficam quase ociosas.

Adaptive capacity percebe e eleva o throughput daquela única partição, puxando da capacidade não usada das partições frias. Sem config, sem custo, sem aquecimento — desde maio de 2019 o impulso é efetivamente instantâneo. (AWS Database Blog, "How DynamoDB adaptive capacity accommodates uneven access patterns".)

empresta WCU ociosaempresta WCU ociosaempresta WCU ociosaTabela: 400 WCUVEHICLE#A1~50 WCU (fria)VEHICLE#B7~50 WCU (fria)VEHICLE#C3~50 WCU (fria)VEHICLE#HOT150 WCU (quente)

A partição da van quente precisa de 150 WCU, mas sua parcela igual de 100 WCU sofreria throttling; adaptive capacity toma emprestada a WCU ociosa das partições frias para cobri-la.

Isolamento: quando um item é o problema

O desequilíbrio nem sempre é por chave — às vezes um único item está incandescente. Se tráfego implacável direciona um item VEHICLE#HOT, o split-for-heat do DynamoDB reequilibra partições para que o item acessado com frequência aterrisse sozinho.

Uma vez isolada, a chave desse único item pode puxar o teto da partição completo: 3.000 RCU e 1.000 WCU. Esse é o teto absoluto para uma chave — não há mecanismo acima dele. (AWS, Key range throughput exceeded.)

Uma ressalva que vale fixar: adaptive capacity não vai dividir uma entre partições quando a tabela tem um . Um LSI amarra a coleção a uma partição — veja GSI vs LSI para o porquê.

Quando adaptive capacity não consegue te salvar

Essa é a armadilha. Ambos os mecanismos movem throughput de um lado para o outro; nenhum cria mais do que uma partição fisicamente permite.

CenárioBurstAdaptiveResultado
Pico curto, tabela com folgaCobreSem throttle
Desequilíbrio sustentado, vizinhos friosTurbina a quenteSem throttle
Um item, < 3K RCU / 1K WCUIsola-oSem throttle
Um item, > teto da partiçãoDrenado rápidoNo tetoCom throttle — precisa redesenhar
Muitas chaves quentes ao mesmo tempo, tabela no máximoDrenado rápidoNada ociosoCom throttle — precisa redesenhar

Se uma única chave legitimamente precisa de mais de 1.000 gravações por segundo, nenhum mecanismo automático te resgata — você precisa espalhar a carga por mais chaves.

Write sharding é a correção usual: acrescente um sufixo (VEHICLE#HOT#0#9) para que as gravações se espalhem pelas partições, depois junte as leituras de volta.

Esse fan-in é em si um padrão de acesso a ser modelado deliberadamente, do mesmo jeito que você planejaria um caminho de consulta em single-table design — adaptive capacity compra tempo, não um passe livre no design de chaves.

Veja na sua própria tabela

Adaptive capacity é invisível por design, então você raciocina sobre ela através de um sintoma: quais chaves estão quentes. Quando você constrói o caminho de gravação com sharding, o Construtor de Expressões gera a sintaxe de PutItem e Query para uma chave com sufixo.

Para observar como uma chave de fato se distribui pelos seus dados, baixe o DynoTable e rode um GROUP BY sobre sua chave de partição no SQL Workbench para ver como os itens se acumulam por chave antes de presumir que adaptive capacity resolveu. Para o lado da leitura do desequilíbrio, veja Query vs Scan.

Atualizado