<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rodolfo Henrique</title>
    <description>The latest articles on DEV Community by Rodolfo Henrique (@rodolfocoding).</description>
    <link>https://dev.to/rodolfocoding</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3137981%2F1df1eb0f-b5c2-4b76-a654-26c51dfc6e4f.jpg</url>
      <title>DEV Community: Rodolfo Henrique</title>
      <link>https://dev.to/rodolfocoding</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rodolfocoding"/>
    <language>en</language>
    <item>
      <title>The 3-2-1-1-0 backup rule. We had everything except the zero</title>
      <dc:creator>Rodolfo Henrique</dc:creator>
      <pubDate>Wed, 07 Oct 2026 00:40:53 +0000</pubDate>
      <link>https://dev.to/rodolfocoding/the-3-2-1-1-0-backup-rule-we-had-everything-except-the-zero-4p2f</link>
      <guid>https://dev.to/rodolfocoding/the-3-2-1-1-0-backup-rule-we-had-everything-except-the-zero-4p2f</guid>
      <description>&lt;h1&gt;
  
  
  The 3-2-1-1-0 backup rule. We had everything except the zero
&lt;/h1&gt;

&lt;p&gt;Backup looks simple until the day you need it.&lt;/p&gt;

&lt;p&gt;In simple terms, a backup means making a copy of your data so it can be recovered if the original is lost, corrupted, or deleted.&lt;/p&gt;

&lt;p&gt;But there is an important difference between having a backup and being able to recover your data from it.&lt;/p&gt;

&lt;p&gt;Imagine that every day an automated process backs up your database. At the end, the system shows a big green mark: the process finished without errors.&lt;/p&gt;

&lt;p&gt;You might think: "everything is protected."&lt;/p&gt;

&lt;p&gt;But what does that green mark actually mean?&lt;/p&gt;

&lt;p&gt;Only that the process was able to run the steps it was supposed to run. By itself, it does not guarantee that the copy is intact, that the data is consistent, or that you can recover it when you really need to.&lt;/p&gt;

&lt;p&gt;This is where the 3-2-1-1-0 rule comes in.&lt;/p&gt;

&lt;p&gt;It is a strategy to reduce the risk of losing data even when something goes wrong. The numbers describe how copies should be kept and protected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3&lt;/strong&gt; copies of the data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2&lt;/strong&gt; different types of media or storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1&lt;/strong&gt; copy kept off the primary environment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1&lt;/strong&gt; isolated or immutable copy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0&lt;/strong&gt; errors during the recovery test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last number is the interesting one.&lt;/p&gt;

&lt;p&gt;Zero is not another copy or another place to store backups. It is a requirement: when it is time to recover the data, the restore has to work.&lt;/p&gt;

&lt;p&gt;Because a backup that has never been restored is, to a point, a hypothesis.&lt;/p&gt;

&lt;p&gt;The scene below is the starting point for understanding that count, and especially the reasoning behind each number.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftnatd7s1wktv00ndmppu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftnatd7s1wktv00ndmppu.jpg" alt="Backup protection strategies: 3 copies of the data, 2 different types of media or storage, 1 copy off the primary environment, 1 isolated or immutable copy, and 0 errors on the recovery test." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What fails when a number is missing
&lt;/h2&gt;

&lt;p&gt;The rule only holds if each number covers a different failure. If two numbers break the same way, you do not have five controls. You have repetition.&lt;/p&gt;

&lt;p&gt;Without the &lt;strong&gt;3&lt;/strong&gt;, production and the "backup" live in the same place. A retention mistake, a broad policy, or a compromised identity deletes the original and the copies together. Three names in one location are not three copies.&lt;/p&gt;

&lt;p&gt;Without the &lt;strong&gt;2&lt;/strong&gt;, the copies use the same media or the same storage service. The failure repeats: corruption, quota, API, region. Two identical disks in the same account fail the same way.&lt;/p&gt;

&lt;p&gt;Without the &lt;strong&gt;1&lt;/strong&gt; off the primary environment, the incident in that environment takes the backup with it. Compromised account, single IdP, unavailable region. The copy has to sit where that incident cannot reach.&lt;/p&gt;

&lt;p&gt;Without the &lt;strong&gt;1&lt;/strong&gt; that is isolated or immutable, whoever reached production also reaches the backup delete. Isolation cuts the easy path. Immutability blocks the delete even when the path appears. Ransomware that hits production usually hits the backup repository next. Without that lock, the way back disappears with the original.&lt;/p&gt;

&lt;p&gt;Without the &lt;strong&gt;0&lt;/strong&gt;, the job is green and the box will not open. The first four numbers say where the copy lives. The zero says whether it comes back.&lt;/p&gt;

&lt;p&gt;That is failure engineering, not a poster. It is still incomplete until restore has been exercised.&lt;/p&gt;

&lt;h2&gt;
  
  
  The green job lies by omission
&lt;/h2&gt;

&lt;p&gt;A successful backup job answers a narrow question: the writer persisted what was requested, to the configured destination, inside the window. It does not answer whether the incremental chain is intact. It does not answer whether the database was captured in a usable state (with a flush, a consistent snapshot, a native backup), or only as a disk in the middle of a write. It does not answer whether the KMS key for restore still exists, whether the identity doing the restore can read the vault, whether the destination engine accepts that version, or whether the time to return fits what the business calls acceptable.&lt;/p&gt;

&lt;p&gt;Integrity means the backup is complete and coherent. Availability means you can reach it and apply it. Neither one is the job's exit code.&lt;/p&gt;

&lt;p&gt;That is why the zero is not a quantity. It is not "one more vault". It is the acceptance criterion: restore on purpose, watch the data come back, measure how long it took, and only then call the design 3-2-1-1-0. Test the job. Test recoverability. Both. One without the other leaves a green check on a box that will not open.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjddj4rg57rju5jmxijle.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjddj4rg57rju5jmxijle.jpg" alt="The backup job is green. The restore failed. A copy is not recovery." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a recovery test has to show
&lt;/h2&gt;

&lt;p&gt;The zero does not ask for a lab. It asks for four answers, obtained on purpose, without panic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;did the data come back?&lt;/li&gt;
&lt;li&gt;did it come back consistent, in a state the application will accept?&lt;/li&gt;
&lt;li&gt;could someone on the team run the restore without inventing permissions, keys, or a destination on the spot?&lt;/li&gt;
&lt;li&gt;does the time to return fit what the business can stand?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any answer is "the job was green", the test has not happened yet. A dashboard measures the writer. Recovery measures the way back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does the backup work when you need it?
&lt;/h2&gt;

&lt;p&gt;"Do we have a backup?"&lt;/p&gt;

&lt;p&gt;That sounds like the right question. In practice, it says little. Most environments can answer yes.&lt;/p&gt;

&lt;p&gt;The question that actually matters is this one:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When was the last time someone restored that backup on purpose, in a real environment, and confirmed that the system came back up?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A dashboard can show that the backup finished successfully. It can show that the copy exists, that storage is healthy, and that the last job completed without errors.&lt;/p&gt;

&lt;p&gt;None of those signals answers whether you can recover the system when you actually need to.&lt;/p&gt;

&lt;p&gt;If the only evidence that the backup works is a green dashboard, you know you have a copy. You might already have the 3, the 2, and both 1s.&lt;/p&gt;

&lt;p&gt;But you are still missing the zero.&lt;/p&gt;

&lt;p&gt;The zero is proof that the way back works.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>backup</category>
      <category>disasterrecovery</category>
      <category>cloud</category>
    </item>
    <item>
      <title>A regra de backup 3-2-1-1-0. Tínhamos tudo, menos o zero</title>
      <dc:creator>Rodolfo Henrique</dc:creator>
      <pubDate>Wed, 07 Oct 2026 00:40:52 +0000</pubDate>
      <link>https://dev.to/rodolfocoding/a-regra-de-backup-3-2-1-1-0-tinhamos-tudo-menos-o-zero-dgn</link>
      <guid>https://dev.to/rodolfocoding/a-regra-de-backup-3-2-1-1-0-tinhamos-tudo-menos-o-zero-dgn</guid>
      <description>&lt;h1&gt;
  
  
  A regra de backup 3-2-1-1-0. Tínhamos tudo, menos o zero
&lt;/h1&gt;

&lt;p&gt;Backup parece simples até o dia em que você precisa dele.&lt;/p&gt;

&lt;p&gt;Em termos simples, fazer backup significa criar uma cópia dos seus dados para que eles possam ser recuperados caso o original seja perdido, corrompido ou apagado.&lt;/p&gt;

&lt;p&gt;Mas existe uma diferença importante entre ter um backup e conseguir recuperar seus dados a partir dele.&lt;/p&gt;

&lt;p&gt;Imagine que todos os dias um processo automatizado execute o backup do seu banco de dados. No final, o sistema mostra um grande sinal verde: o processo terminou sem erros.&lt;/p&gt;

&lt;p&gt;Você pode pensar: "está tudo protegido".&lt;/p&gt;

&lt;p&gt;Mas o que esse sinal verde realmente significa?&lt;/p&gt;

&lt;p&gt;Apenas que o processo conseguiu executar as etapas previstas. Ele não garante, sozinho, que a cópia esteja íntegra, que os dados estejam consistentes ou que seja possível recuperá-los quando você realmente precisar.&lt;/p&gt;

&lt;p&gt;É aqui que entra a regra 3-2-1-1-0.&lt;/p&gt;

&lt;p&gt;Ela é uma estratégia para reduzir o risco de perder os dados mesmo quando alguma coisa dá errado. Os números representam como as cópias devem ser mantidas e protegidas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;3&lt;/strong&gt; cópias dos dados&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2&lt;/strong&gt; tipos diferentes de mídia ou armazenamento&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1&lt;/strong&gt; cópia mantida fora do ambiente principal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1&lt;/strong&gt; cópia isolada ou imutável&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;0&lt;/strong&gt; erros durante o teste de recuperação&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O último número é o mais interessante.&lt;/p&gt;

&lt;p&gt;O zero não representa mais uma cópia ou outro lugar para armazenar seus backups. Ele representa uma exigência: quando chegar a hora de recuperar os dados, o restore precisa funcionar.&lt;/p&gt;

&lt;p&gt;Porque backup que nunca foi restaurado é, até certo ponto, uma hipótese.&lt;/p&gt;

&lt;p&gt;A cena abaixo é o ponto de partida para entender essa conta e, principalmente, a lógica por trás de cada número.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm8gkx5ee11ima0aggd5l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm8gkx5ee11ima0aggd5l.jpg" alt="Estratégias de proteção do backup: 3 cópias dos dados, 2 tipos diferentes de mídia ou armazenamento, 1 cópia fora do ambiente principal, 1 cópia isolada ou imutável, e 0 erros no teste de recuperação." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que falha quando falta um número
&lt;/h2&gt;

&lt;p&gt;A regra só vale se cada número segura uma falha diferente. Se dois números quebram do mesmo jeito, você não tem cinco controles. Tem repetição.&lt;/p&gt;

&lt;p&gt;Sem o &lt;strong&gt;3&lt;/strong&gt;, produção e “backup” moram no mesmo destino. Um erro de retenção, uma policy larga ou uma identidade comprometida apaga o original e as cópias juntas. Três nomes no mesmo lugar não são três cópias.&lt;/p&gt;

&lt;p&gt;Sem o &lt;strong&gt;2&lt;/strong&gt;, as cópias usam o mesmo tipo de mídia ou o mesmo serviço de armazenamento. A falha se repete: corrupção, quota, API, região. Dois discos iguais, na mesma conta, falham do mesmo jeito.&lt;/p&gt;

&lt;p&gt;Sem o &lt;strong&gt;1&lt;/strong&gt; fora do ambiente principal, o incidente do ambiente leva o backup junto. Conta comprometida, IdP único, região indisponível. A cópia precisa estar onde esse incidente não alcança.&lt;/p&gt;

&lt;p&gt;Sem o &lt;strong&gt;1&lt;/strong&gt; isolado ou imutável, quem chegou na produção também chega no delete do backup. Isolamento corta o caminho fácil. Imutabilidade impede o delete mesmo quando o caminho aparece. Ransomware que mira produção costuma mirar o repositório de backup em seguida. Sem essa trava, a via de volta some com o original.&lt;/p&gt;

&lt;p&gt;Sem o &lt;strong&gt;0&lt;/strong&gt;, o job está verde e a caixa não abre. Os quatro primeiros números respondem onde a cópia está. O zero responde se ela volta.&lt;/p&gt;

&lt;p&gt;Isso é engenharia de falha, não poster. Ainda assim é incompleto enquanto o restore não for exercitado.&lt;/p&gt;

&lt;h2&gt;
  
  
  O job verde mente por omissão
&lt;/h2&gt;

&lt;p&gt;Um job de backup bem-sucedido responde a uma pergunta estreita: o writer conseguiu persistir o que foi pedido, no destino configurado, dentro da janela. Ele não responde se a cadeia incremental está íntegra. Não responde se o banco foi capturado em estado aplicável (com flush, com snapshot consistente, com backup nativo), ou só como um disco no meio de um write. Não responde se a chave KMS do restore ainda existe, se a identity que restaura tem permissão no cofre, se o engine de destino aceita aquela versão, se o tempo de volta cabe no que o negócio chama de aceitável.&lt;/p&gt;

&lt;p&gt;Integridade é o backup estar completo e coerente. Disponibilidade é conseguir acessá-lo e aplicá-lo. Nenhuma das duas é o exit code do job.&lt;/p&gt;

&lt;p&gt;Por isso o zero não é quantidade. Não é “mais um vault”. É o critério de aceite: restaurar de propósito, ver o dado voltar, medir quanto tempo levou, e só então chamar o desenho de 3-2-1-1-0. Teste do job. Teste da recuperabilidade. Os dois. Um sem o outro deixa um check verde em cima de uma caixa que não abre.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb9s0nm7url7dgo81ovyl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb9s0nm7url7dgo81ovyl.jpg" alt="O job de backup está verde. O restore falhou. Cópia não é recuperação." width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que o teste de recuperação precisa mostrar
&lt;/h2&gt;

&lt;p&gt;O zero não pede um laboratório. Pede quatro respostas, obtidas de propósito, sem pânico:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;o dado voltou?&lt;/li&gt;
&lt;li&gt;voltou consistente, num estado que a aplicação aceita?&lt;/li&gt;
&lt;li&gt;alguém do time conseguiu fazer o restore sem improvisar permissão, chave ou destino?&lt;/li&gt;
&lt;li&gt;o tempo de volta cabe no que o negócio aguenta?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se alguma resposta for “o job estava verde”, o teste ainda não aconteceu. Dashboard mede o writer. Recuperação mede o caminho de volta.&lt;/p&gt;

&lt;h2&gt;
  
  
  O backup funciona quando você precisa dele?
&lt;/h2&gt;

&lt;p&gt;"Temos backup?"&lt;/p&gt;

&lt;p&gt;Essa parece ser a pergunta certa. Mas, na prática, ela diz pouco. A maioria dos ambientes consegue responder que sim.&lt;/p&gt;

&lt;p&gt;A pergunta que realmente importa é outra:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quando foi a última vez que alguém restaurou esse backup de propósito, em um ambiente real, e confirmou que o sistema voltou a funcionar?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Um dashboard pode mostrar que o backup terminou com sucesso. Pode mostrar que a cópia existe, que o armazenamento está saudável e que o último job foi concluído sem erros.&lt;/p&gt;

&lt;p&gt;Mas nenhum desses indicadores responde se você consegue recuperar o sistema quando realmente precisar.&lt;/p&gt;

&lt;p&gt;Se a única evidência de que o backup funciona é um dashboard verde, você sabe que tem uma cópia. Talvez já tenha o 3, o 2 e os dois 1.&lt;/p&gt;

&lt;p&gt;Mas ainda falta o zero.&lt;/p&gt;

&lt;p&gt;O zero é a prova de que o caminho de volta funciona.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>backup</category>
      <category>disasterrecovery</category>
      <category>cloud</category>
    </item>
    <item>
      <title>A classe mais barata do S3 é a que você nunca abre</title>
      <dc:creator>Rodolfo Henrique</dc:creator>
      <pubDate>Mon, 28 Sep 2026 22:36:13 +0000</pubDate>
      <link>https://dev.to/rodolfocoding/a-classe-mais-barata-do-s3-e-a-que-voce-nunca-abre-4hp6</link>
      <guid>https://dev.to/rodolfocoding/a-classe-mais-barata-do-s3-e-a-que-voce-nunca-abre-4hp6</guid>
      <description>&lt;h1&gt;
  
  
  A classe mais barata do S3 é a que você nunca abre
&lt;/h1&gt;

&lt;p&gt;Um time tira alguns milhões de objetos do S3 Standard. O armazenamento por gigabyte cai. O financeiro respira. Dois meses depois alguém roda um job que lê quase o prefixo inteiro. A fatura não ficou mais barata. Ficou uma taxa de retrieval com uma storage class colada.&lt;/p&gt;

&lt;p&gt;Esse é o erro clássico do S3. A pessoa otimiza o preço de &lt;em&gt;guardar&lt;/em&gt; o byte. A conta também cobra por &lt;em&gt;tocar&lt;/em&gt; nele, por apagar cedo demais e por objeto menor do que a classe quer faturar.&lt;/p&gt;

&lt;p&gt;Se você guardar uma coisa: escolha a classe pela frequência de leitura, pela velocidade que essa leitura precisa ter e por conseguir ou não reconstruir o objeto se uma zona sumir. O resto é casar essas três respostas com uma classe que a AWS já nomeou.&lt;/p&gt;

&lt;p&gt;Referência oficial: &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html" rel="noopener noreferrer"&gt;Understanding and managing Amazon S3 storage classes&lt;/a&gt;. Preço fica em &lt;a href="https://aws.amazon.com/s3/pricing/" rel="noopener noreferrer"&gt;Amazon S3 pricing&lt;/a&gt;. Este artigo não cita valor em dólar. Isso muda por região e por data. O formato da troca não muda.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequência é o enredo inteiro
&lt;/h2&gt;

&lt;p&gt;S3 Standard é o padrão. Sobe o objeto, não manda o header de storage class, você está em Standard. &lt;code&gt;GET&lt;/code&gt; em milissegundo. Projetada para 99,99% de disponibilidade em pelo menos três Availability Zones. Sem duração mínima de armazenamento. Sem tamanho mínimo faturável. Você paga mais por GB guardado do que nas classes de arquivo, e não paga retrieval por GB numa leitura normal.&lt;/p&gt;

&lt;p&gt;Use quando o objeto está no caminho da requisição: imagem de produto, artefato de sessão, o dataset que a API bate esta semana, qualquer coisa que você teria vergonha de restaurar de um arquivo enquanto o usuário espera.&lt;/p&gt;

&lt;p&gt;Não use como sótão de dez anos. Tecnicamente dá. Você vai pagar Standard em dado que ninguém abre.&lt;/p&gt;

&lt;p&gt;A armadilha do outro lado é jogar &lt;em&gt;tudo&lt;/em&gt; numa classe infrequent ou Glacier porque a linha de storage é menor. Infrequent-access e Glacier somam cobrança de retrieval. Várias delas também faturam duração mínima e tamanho mínimo de objeto. Um prefixo cheio de arquivo miúdo que você reescreve toda semana é um encaixe ruim nessas classes, mesmo se você "quase nunca" pensa neles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando você não conhece o padrão de acesso
&lt;/h2&gt;

&lt;p&gt;S3 Intelligent-Tiering existe para a resposta honesta: "ainda não sei."&lt;/p&gt;

&lt;p&gt;A AWS desenhou para acesso desconhecido, que muda, ou imprevisível. Ela observa os objetos e move entre tiers quando esfriam, e volta para Frequent Access se alguém lê de novo. Não tem taxa de retrieval dentro do Intelligent-Tiering. Você paga monitoramento e automação por objeto.&lt;/p&gt;

&lt;p&gt;Tiers automáticos, pela documentação atual:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequent Access: onde o objeto novo começa.&lt;/li&gt;
&lt;li&gt;Infrequent Access: depois de 30 dias seguidos sem acesso.&lt;/li&gt;
&lt;li&gt;Archive Instant Access: depois de 90 dias seguidos sem acesso. Continua milissegundo, alto throughput.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Opcionais, só se a aplicação puder esperar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Archive Access: assíncrono. Mesmo formato de performance do S3 Glacier Flexible Retrieval. Restore standard costuma levar de 3 a 5 horas.&lt;/li&gt;
&lt;li&gt;Deep Archive Access: assíncrono. Mesmo formato de performance do S3 Glacier Deep Archive. Restore standard costuma ficar dentro de 12 horas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Objeto menor que 128 KB não é monitorado. Fica em Frequent Access. Se o bucket é milhões de objetos miúdos, a taxa de monitoramento pode dominar e o auto-tiering nunca começa. Nesse caso Intelligent-Tiering é o default errado.&lt;/p&gt;

&lt;p&gt;Encaixa bem: data lake, dump de analytics, prefixo de produto novo cujo padrão de leitura você só vai aprender em produção.&lt;/p&gt;

&lt;p&gt;Encaixa mal: caminho quente que você já conhece (use Standard), ou arquivo conhecido que você não vai ler por anos (pule a taxa de monitoramento e coloque no Glacier de propósito).&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrequent não é "Standard mais barato"
&lt;/h2&gt;

&lt;p&gt;S3 Standard-IA e S3 One Zone-IA mantêm acesso em milissegundo, como o Standard. A AWS descreve como dado de vida longa que você toca mais ou menos uma vez por mês. As duas cobram retrieval por GB. As duas têm 30 dias de duração mínima e 128 KB de tamanho mínimo faturável. Apagar, sobrescrever ou transicionar antes de 30 dias ainda cobra o resto do mês, proporcional.&lt;/p&gt;

&lt;p&gt;Por isso "mover para IA no segundo dia" pode sair mais caro do que deixar no Standard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standard-IA&lt;/strong&gt; guarda o objeto em pelo menos três Availability Zones. Projetada para 99,9% de disponibilidade. Orientação da própria AWS: use para a cópia principal que você não consegue recriar. Backup que você pode precisar restaurar neste trimestre, dado antigo da aplicação que ainda precisa servir um &lt;code&gt;GET&lt;/code&gt; em milissegundo, arquivo de compliance quieto mas não congelado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One Zone-IA&lt;/strong&gt; guarda o objeto numa Availability Zone só. Projetada para 99,5% de disponibilidade. Storage mais barato. &lt;strong&gt;Não&lt;/strong&gt; aguenta a perda daquela zona. A AWS é explícita: use para dado que você reconstrói, ou para réplica, não como única cópia de algo que você não substitui.&lt;/p&gt;

&lt;p&gt;Se o objeto é a única cópia das notas fiscais do ano passado, One Zone-IA é o tipo errado de barato.&lt;/p&gt;

&lt;h2&gt;
  
  
  Glacier são três produtos diferentes que compartilham o nome da montanha
&lt;/h2&gt;

&lt;p&gt;Ainda se fala "joga no Glacier" como se fosse um botão. São três classes com três histórias de retrieval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S3 Glacier Instant Retrieval.&lt;/strong&gt; Preço de arquivo, &lt;code&gt;GET&lt;/code&gt; em milissegundo. Feita para dado de vida longa que você talvez toque uma vez por trimestre. Mínimo de 90 dias. Mínimo faturável de 128 KB. Tem taxa de retrieval. O objeto fica disponível em tempo real. É a classe do "quase nunca abrimos, mas quando o jurídico pede, quer agora."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S3 Glacier Flexible Retrieval.&lt;/strong&gt; O objeto está arquivado. Um &lt;code&gt;GET&lt;/code&gt; normal não devolve os bytes até você restaurar. Mínimo de 90 dias. Metadado extra é cobrado por objeto (40 KB: 32 KB na tarifa Glacier Flexible, 8 KB na Standard, para o S3 ainda listar a key). Opções de retrieval na documentação atual de restore:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Opção&lt;/th&gt;
&lt;th&gt;Tempo típico (Flexible Retrieval)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Expedited&lt;/td&gt;
&lt;td&gt;1 a 5 minutos para objeto abaixo de 250 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;3 a 5 horas (minutos a 5 horas com Batch Operations)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bulk&lt;/td&gt;
&lt;td&gt;5 a 12 horas, retrieve de menor custo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Bulk retrieval em objeto no Flexible Retrieval é gratuito. Expedited é caminho premium. Sem capacidade provisionada, Expedited pode ser recusado sob carga.&lt;/p&gt;

&lt;p&gt;Use Flexible Retrieval para restore grande que você consegue planejar: dump anual, árvore de disaster recovery que você espera nunca tocar, arquivo em que "ainda hoje à tarde" serve.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S3 Glacier Deep Archive.&lt;/strong&gt; Menor custo de storage desta família. Mínimo de 180 dias. Mesmo estilo de cobrança extra de metadado. Restaura primeiro, depois lê. Expedited não existe. Restore standard costuma ficar dentro de 12 horas (cerca de 9 a 12 horas com Batch Operations). Bulk costuma ficar dentro de 48 horas.&lt;/p&gt;

&lt;p&gt;Use para dado que você guarda porque a política falou "sete anos", não porque um engenheiro vai dar &lt;code&gt;curl&lt;/code&gt; numa terça.&lt;/p&gt;

&lt;p&gt;Restore não é uma cópia sentada ao lado do arquivo para sempre. Você restaura por um número de dias, depois a cópia temporária expira. Se o runbook diz "é só dar GET no objeto", Deep Archive quebra esse runbook.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uma decisão que cabe numa passada
&lt;/h2&gt;

&lt;p&gt;Passe o objeto (ou o prefixo) por estas perguntas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Alguma coisa trava neste &lt;code&gt;GET&lt;/code&gt;?&lt;/strong&gt; Requisição do usuário, API, etapa de pipeline. Fique no Standard, nos tiers instantâneos do Intelligent-Tiering, no Instant Retrieval ou no Express One Zone. Não coloque no Flexible Retrieval nem no Deep Archive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eu conheço o padrão de acesso?&lt;/strong&gt; Não: Intelligent-Tiering, se o objeto for grande o bastante para monitorar. Sim, quente: Standard. Sim, frio mas instantâneo: Standard-IA ou Instant Retrieval. Sim, frio e assíncrono: Flexible Retrieval ou Deep Archive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consigo recriar se uma AZ sumir?&lt;/strong&gt; Não: não use One Zone-IA (nem Express One Zone) como única cópia.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quanto tempo vai viver, e qual o tamanho?&lt;/strong&gt; Menos de 30 dias ou muitos objetos abaixo de 128 KB: IA e Instant Retrieval vão faturar como se o objeto fosse maior e mais velho do que é.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quem paga se a gente ler o prefixo inteiro?&lt;/strong&gt; Se um job mensal varre tudo, classe com preço de retrieval pode ganhar do Standard no storage e perder no job.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Classe&lt;/th&gt;
&lt;th&gt;Acesso&lt;/th&gt;
&lt;th&gt;Restore primeiro?&lt;/th&gt;
&lt;th&gt;Duração mínima&lt;/th&gt;
&lt;th&gt;Tamanho mínimo faturável&lt;/th&gt;
&lt;th&gt;Zonas&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;Milissegundo, frequente&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;td&gt;Nenhuma&lt;/td&gt;
&lt;td&gt;Nenhum&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intelligent-Tiering&lt;/td&gt;
&lt;td&gt;Milissegundo nos tiers automáticos&lt;/td&gt;
&lt;td&gt;Só nos tiers opcionais de arquivo&lt;/td&gt;
&lt;td&gt;Nenhuma&lt;/td&gt;
&lt;td&gt;Nenhum (abaixo de 128 KB fica Frequent)&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard-IA&lt;/td&gt;
&lt;td&gt;Milissegundo, infrequent&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;td&gt;30 dias&lt;/td&gt;
&lt;td&gt;128 KB&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One Zone-IA&lt;/td&gt;
&lt;td&gt;Milissegundo, infrequent&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;td&gt;30 dias&lt;/td&gt;
&lt;td&gt;128 KB&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glacier Instant Retrieval&lt;/td&gt;
&lt;td&gt;Milissegundo, raro&lt;/td&gt;
&lt;td&gt;Não&lt;/td&gt;
&lt;td&gt;90 dias&lt;/td&gt;
&lt;td&gt;128 KB&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glacier Flexible Retrieval&lt;/td&gt;
&lt;td&gt;Minutos a horas&lt;/td&gt;
&lt;td&gt;Sim&lt;/td&gt;
&lt;td&gt;90 dias&lt;/td&gt;
&lt;td&gt;Overhead de metadado&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glacier Deep Archive&lt;/td&gt;
&lt;td&gt;Horas&lt;/td&gt;
&lt;td&gt;Sim&lt;/td&gt;
&lt;td&gt;180 dias&lt;/td&gt;
&lt;td&gt;Overhead de metadado&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A durabilidade projetada dessas classes é 99,999999999%, na mesma tabela de comparação. Disponibilidade não é o mesmo número. Standard e Flexible Retrieval (depois do restore) são projetadas para 99,99%. Standard-IA, Intelligent-Tiering e Instant Retrieval são projetadas para 99,9%. One Zone-IA é projetada para 99,5%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pilhas concretas de objeto
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Lê todo dia.&lt;/strong&gt; Thumbnail, config atual, working set de um serviço. S3 Standard. Lifecycle depois, não no primeiro dia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lê de vez em quando, ainda precisa de GET rápido.&lt;/strong&gt; Relatório do trimestre passado, "baixar nota" de um pedido antigo. Standard-IA se o objeto for grande o bastante e for viver mais de 30 dias. Instant Retrieval se a leitura estiver mais perto de uma vez por trimestre do que uma vez por mês.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backup.&lt;/strong&gt; Se o restore é incêndio e precisa ser rápido, Standard-IA ou Instant Retrieval. Se o restore é um fim de semana planejado, Flexible Retrieval. Se o restore é "a gente guarda porque o audit pediu", Deep Archive. One Zone-IA só se outra região ou outro sistema já tiver uma cópia em que você confia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Guardar por anos, quase nunca abrir.&lt;/strong&gt; Deep Archive. Coloque um lifecycle no prefixo para não depender de alguém lembrar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Job que pode varrer o prefixo.&lt;/strong&gt; Prefira Standard ou Intelligent-Tiering. Taxa de retrieval em IA e Instant Retrieval é precificada para leitura rara, não para "reprocessamos o lake."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acesso desconhecido, objeto que não é miúdo.&lt;/strong&gt; Intelligent-Tiering como classe padrão no &lt;code&gt;PutObject&lt;/code&gt; (&lt;code&gt;x-amz-storage-class: INTELLIGENT_TIERING&lt;/code&gt;). Deixe os tiers opcionais assíncronos de arquivo desligados até a aplicação souber restaurar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mais uma classe se o problema de verdade for latência
&lt;/h2&gt;

&lt;p&gt;A documentação atual também lista &lt;strong&gt;S3 Express One Zone&lt;/strong&gt;: acesso em milissegundo de um dígito numa Availability Zone só, directory bucket, feito para compute sensível a latência perto do dado. Projetada para 99,95% de disponibilidade. Não substitui Standard numa API multi-AZ. Não é classe de arquivo. Se a dor é "Standard está lento demais neste loop apertado", leia aquela página. Se a dor é a fatura, é a página errada.&lt;/p&gt;

&lt;p&gt;A AWS ainda documenta Reduced Redundancy Storage. A mesma página pede para não usar. Standard é o substituto.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como o time costuma errar isso
&lt;/h2&gt;

&lt;p&gt;Eles tratam uma classe como se fosse do bucket. Classe é por objeto. Regra de lifecycle move prefixo conforme envelhece: Standard por 30 dias, Standard-IA depois, Instant Retrieval ou Flexible Retrieval um ano mais tarde. Você não precisa de um bucket novo para cada classe.&lt;/p&gt;

&lt;p&gt;Eles esquecem que overwrite e delete entram na duração mínima. Um prefixo "barato" de IA que é trocado a cada deploy não é infrequent. É Standard com taxa extra.&lt;/p&gt;

&lt;p&gt;Eles tratam Glacier como pasta. O objeto continua no S3. Flexible Retrieval e Deep Archive só não fazem &lt;code&gt;GET&lt;/code&gt; até o &lt;code&gt;RestoreObject&lt;/code&gt; terminar.&lt;/p&gt;

&lt;p&gt;Eles otimizam storage e ignoram listagem, monitoramento e restore. A taxa por objeto do Intelligent-Tiering e os bytes de metadado do Glacier são reais. Pesam mais quando o objeto é pequeno e numeroso.&lt;/p&gt;

&lt;h2&gt;
  
  
  Um default que você consegue defender
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Caminho quente, conhecido: &lt;strong&gt;Standard&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Desconhecido, objeto que vale monitorar: &lt;strong&gt;Intelligent-Tiering&lt;/strong&gt;, só os tiers automáticos.&lt;/li&gt;
&lt;li&gt;Frio, precisa de &lt;code&gt;GET&lt;/code&gt; agora, multi-AZ: &lt;strong&gt;Standard-IA&lt;/strong&gt; ou &lt;strong&gt;Instant Retrieval&lt;/strong&gt;, conforme a raridade da leitura.&lt;/li&gt;
&lt;li&gt;Frio, precisa de &lt;code&gt;GET&lt;/code&gt; agora, você reconstrói: &lt;strong&gt;One Zone-IA&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Frio, você aguenta esperar horas: &lt;strong&gt;Flexible Retrieval&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Frio, você aguenta esperar um dia, vai guardar por anos: &lt;strong&gt;Deep Archive&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se ainda parecer chute, não chute Glacier. Chute Intelligent-Tiering ou Standard, e coloque um lifecycle quando tiver log de acesso de verdade. A classe cara é a que te surpreende quando alguém finalmente abre o objeto.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3</category>
      <category>cloud</category>
      <category>storage</category>
    </item>
    <item>
      <title>The cheapest S3 class is the one you never open</title>
      <dc:creator>Rodolfo Henrique</dc:creator>
      <pubDate>Mon, 28 Sep 2026 22:32:20 +0000</pubDate>
      <link>https://dev.to/rodolfocoding/the-cheapest-s3-class-is-the-one-you-never-open-3c3l</link>
      <guid>https://dev.to/rodolfocoding/the-cheapest-s3-class-is-the-one-you-never-open-3c3l</guid>
      <description>&lt;p&gt;A team moves a few million objects out of S3 Standard. Storage per gigabyte drops. Finance is happy. Two months later someone runs a job that reads most of the prefix. The invoice does not look cheaper. It looks like a retrieval fee with a storage class attached.&lt;/p&gt;

&lt;p&gt;That is the usual S3 mistake. People optimize the price of &lt;em&gt;keeping&lt;/em&gt; a byte. The bill also charges you for &lt;em&gt;touching&lt;/em&gt; it, for deleting it too soon, and for objects that are smaller than the class wants to bill.&lt;/p&gt;

&lt;p&gt;If you remember one thing: pick a class for how often the object is read, how fast the read must be, and whether you can rebuild the object if a zone disappears. The rest is matching those three answers to a class AWS already named.&lt;/p&gt;

&lt;p&gt;Official reference: &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html" rel="noopener noreferrer"&gt;Understanding and managing Amazon S3 storage classes&lt;/a&gt;. Pricing lives on &lt;a href="https://aws.amazon.com/s3/pricing/" rel="noopener noreferrer"&gt;Amazon S3 pricing&lt;/a&gt;. This article does not quote dollar amounts. Those change by region and date. The shape of the trade-off does not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequency is the whole plot
&lt;/h2&gt;

&lt;p&gt;S3 Standard is the default. Upload an object, skip the storage-class header, you are in Standard. Millisecond &lt;code&gt;GET&lt;/code&gt;. Designed for 99.99% availability across at least three Availability Zones. No minimum storage duration. No minimum billable object size. You pay more per GB stored than the archive classes, and you do not pay a per-GB retrieval fee for a normal read.&lt;/p&gt;

&lt;p&gt;Use it when the object is part of the request path: product images, session artifacts, the dataset the API hits this week, anything you would be embarrassed to restore from an archive while a user waits.&lt;/p&gt;

&lt;p&gt;Do not use it as a ten-year attic. You can, technically. You will pay Standard rates for data nobody opens.&lt;/p&gt;

&lt;p&gt;The trap on the other side is dumping &lt;em&gt;everything&lt;/em&gt; into an infrequent or Glacier class because the storage line is lower. Infrequent-access and Glacier classes add retrieval charges. Several of them also bill a minimum duration and a minimum object size. A prefix full of tiny files that you rewrite every week is a bad fit for those classes even if you "almost never" think about them.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you do not know the access pattern
&lt;/h2&gt;

&lt;p&gt;S3 Intelligent-Tiering exists for the honest answer: "I do not know yet."&lt;/p&gt;

&lt;p&gt;AWS designed it for unknown, changing, or unpredictable access. It monitors objects and moves them between tiers as they go cold, then back to Frequent Access if they are read again. There are no retrieval fees inside Intelligent-Tiering. You pay a per-object monitoring and automation charge instead.&lt;/p&gt;

&lt;p&gt;Automatic tiers, from the current docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frequent Access: where new objects start.&lt;/li&gt;
&lt;li&gt;Infrequent Access: after 30 consecutive days with no access.&lt;/li&gt;
&lt;li&gt;Archive Instant Access: after 90 consecutive days with no access. Still millisecond, high-throughput access.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional, only if your app can wait:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Archive Access: asynchronous. Same performance shape as S3 Glacier Flexible Retrieval. Standard restore is typically 3 to 5 hours.&lt;/li&gt;
&lt;li&gt;Deep Archive Access: asynchronous. Same performance shape as S3 Glacier Deep Archive. Standard restore is typically within 12 hours.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Objects smaller than 128 KB are not monitored. They stay in Frequent Access. If your bucket is millions of tiny objects, the monitoring fee can dominate and the auto-tiering never starts. In that case Intelligent-Tiering is the wrong default.&lt;/p&gt;

&lt;p&gt;Good fit: a data lake, analytics dumps, a new product prefix whose read pattern you will only learn in production.&lt;/p&gt;

&lt;p&gt;Bad fit: a well-known hot path (just use Standard), or a known archive you will not read for years (skip the monitoring fee and put it in Glacier on purpose).&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrequent does not mean "cheaper Standard"
&lt;/h2&gt;

&lt;p&gt;S3 Standard-IA and S3 One Zone-IA keep millisecond access, like Standard. AWS describes them as long-lived data you touch about once a month. Both charge a per-GB retrieval fee. Both have a 30-day minimum storage duration and a 128 KB minimum billable object size. Delete, overwrite, or transition before 30 days and you still pay the rest of the month, prorated.&lt;/p&gt;

&lt;p&gt;That is why "move it to IA on day two" can cost more than leaving it in Standard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standard-IA&lt;/strong&gt; stores the object across at least three Availability Zones. Designed for 99.9% availability. AWS's own guidance: use this for a primary copy you cannot recreate. Backups you might restore this quarter, older app data that still has to serve a &lt;code&gt;GET&lt;/code&gt; in milliseconds, compliance files that are quiet but not frozen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One Zone-IA&lt;/strong&gt; stores the object in a single Availability Zone. Designed for 99.5% availability. Cheaper storage. It is &lt;strong&gt;not&lt;/strong&gt; resilient to the loss of that zone. AWS is explicit: use it for data you can rebuild, or for replicas, not as the only copy of something you cannot replace.&lt;/p&gt;

&lt;p&gt;If the object is the company's only copy of last year's invoices, One Zone-IA is the wrong kind of cheap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Glacier is three different products that share a mountain name
&lt;/h2&gt;

&lt;p&gt;People still say "put it in Glacier" as if that were one button. It is three classes with three retrieval stories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S3 Glacier Instant Retrieval.&lt;/strong&gt; Archive pricing, millisecond &lt;code&gt;GET&lt;/code&gt;. Designed for long-lived data you might touch about once a quarter. 90-day minimum. 128 KB minimum billable size. Retrieval fees apply. The object is available in real time. This is the class for "we almost never open it, but when legal asks, they want it now."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S3 Glacier Flexible Retrieval.&lt;/strong&gt; The object is archived. A normal &lt;code&gt;GET&lt;/code&gt; does not return the bytes until you restore it. 90-day minimum. Extra metadata is billed per object (40 KB: 32 KB at the Glacier Flexible rate, 8 KB at Standard, so S3 can still list the key). Retrieval options from the current restore docs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Typical time (Flexible Retrieval)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Expedited&lt;/td&gt;
&lt;td&gt;1 to 5 minutes for objects under 250 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;3 to 5 hours (minutes to 5 hours with Batch Operations)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bulk&lt;/td&gt;
&lt;td&gt;5 to 12 hours, lowest-cost retrieve&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Bulk retrievals are free for objects in Flexible Retrieval. Expedited is a premium path. Without provisioned capacity, Expedited can be refused under load.&lt;/p&gt;

&lt;p&gt;Use Flexible Retrieval for large restores you can plan: yearly dumps, disaster-recovery trees you hope never to touch, archives where "this afternoon" is acceptable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;S3 Glacier Deep Archive.&lt;/strong&gt; Lowest storage cost in this family. 180-day minimum. Same style of extra metadata billing. Restore first, then read. Expedited is not available. Standard restore is typically within 12 hours (about 9 to 12 hours with Batch Operations). Bulk is typically within 48 hours.&lt;/p&gt;

&lt;p&gt;Use it for data you are keeping because a policy said "seven years," not because an engineer will &lt;code&gt;curl&lt;/code&gt; it on a Tuesday.&lt;/p&gt;

&lt;p&gt;A restore is not a copy sitting next to the archive forever. You restore for a number of days, then the temporary copy expires. If the runbook says "just GET the object," Deep Archive will fail that runbook.&lt;/p&gt;

&lt;h2&gt;
  
  
  A decision you can make in one pass
&lt;/h2&gt;

&lt;p&gt;Walk the object (or the prefix) through these questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Will something block on this &lt;code&gt;GET&lt;/code&gt;?&lt;/strong&gt; User request, API, pipeline step. Stay in Standard, Intelligent-Tiering's instant tiers, Instant Retrieval, or Express One Zone. Do not put it in Flexible Retrieval or Deep Archive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Do I know the access pattern?&lt;/strong&gt; No: Intelligent-Tiering, if objects are large enough to monitor. Yes, hot: Standard. Yes, cold but instant: Standard-IA or Instant Retrieval. Yes, cold and async: Flexible Retrieval or Deep Archive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Can I recreate it if one AZ is gone?&lt;/strong&gt; No: do not use One Zone-IA (or Express One Zone) as the only copy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How long will it live, and how big is it?&lt;/strong&gt; Under 30 days or lots of sub-128 KB objects: IA and Instant Retrieval will bill you as if the objects were larger and older than they are.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Who pays if we read the whole prefix?&lt;/strong&gt; If a monthly job scans everything, retrieval-priced classes can beat Standard on storage and lose on the job.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;th&gt;Access&lt;/th&gt;
&lt;th&gt;Restore first?&lt;/th&gt;
&lt;th&gt;Min duration&lt;/th&gt;
&lt;th&gt;Min billable size&lt;/th&gt;
&lt;th&gt;Zones&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;Millisecond, frequent&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intelligent-Tiering&lt;/td&gt;
&lt;td&gt;Millisecond in the automatic tiers&lt;/td&gt;
&lt;td&gt;Only in optional archive tiers&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;None (under 128 KB stays Frequent)&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard-IA&lt;/td&gt;
&lt;td&gt;Millisecond, infrequent&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;30 days&lt;/td&gt;
&lt;td&gt;128 KB&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One Zone-IA&lt;/td&gt;
&lt;td&gt;Millisecond, infrequent&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;30 days&lt;/td&gt;
&lt;td&gt;128 KB&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glacier Instant Retrieval&lt;/td&gt;
&lt;td&gt;Millisecond, rare&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;90 days&lt;/td&gt;
&lt;td&gt;128 KB&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glacier Flexible Retrieval&lt;/td&gt;
&lt;td&gt;Minutes to hours&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;90 days&lt;/td&gt;
&lt;td&gt;Metadata overhead&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Glacier Deep Archive&lt;/td&gt;
&lt;td&gt;Hours&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;180 days&lt;/td&gt;
&lt;td&gt;Metadata overhead&lt;/td&gt;
&lt;td&gt;&amp;gt;= 3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Designed-for durability for these classes is 99.999999999%, per the same comparison table. Availability is not the same number. Standard and Flexible Retrieval (after restore) are designed for 99.99%. Standard-IA, Intelligent-Tiering, and Instant Retrieval are designed for 99.9%. One Zone-IA is designed for 99.5%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concrete piles of objects
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Read every day.&lt;/strong&gt; Thumbnails, current config, the working set of a service. S3 Standard. Lifecycle later, not on day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read now and then, still need a fast GET.&lt;/strong&gt; Last quarter's reports, "download invoice" on an old order. Standard-IA if the objects are large enough and will live past 30 days. Instant Retrieval if the read is closer to once a quarter than once a month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backups.&lt;/strong&gt; If restore is a fire drill and has to be fast, Standard-IA or Instant Retrieval. If restore is a planned weekend, Flexible Retrieval. If restore is "we keep this because audit said so," Deep Archive. One Zone-IA only if another region or another system already has a copy you trust.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep it for years, almost never open it.&lt;/strong&gt; Deep Archive. Put a lifecycle on the prefix so you do not rely on a human remembering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A job that might scan the prefix.&lt;/strong&gt; Prefer Standard or Intelligent-Tiering. Retrieval fees on IA and Instant Retrieval are priced for rare reads, not for "we reprocessed the lake."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unknown access, objects not tiny.&lt;/strong&gt; Intelligent-Tiering as the default class on &lt;code&gt;PutObject&lt;/code&gt; (&lt;code&gt;x-amz-storage-class: INTELLIGENT_TIERING&lt;/code&gt;). Leave the optional async archive tiers off until the application can restore.&lt;/p&gt;

&lt;h2&gt;
  
  
  One more class if latency is the actual problem
&lt;/h2&gt;

&lt;p&gt;The current docs also list &lt;strong&gt;S3 Express One Zone&lt;/strong&gt;: single-digit millisecond access in one Availability Zone, directory buckets, built for latency-sensitive compute next to the data. Designed for 99.95% availability. Not a replacement for Standard in a multi-AZ API. Not an archive class. If the pain is "Standard is too slow for this tight loop," read that page. If the pain is the bill, it is the wrong page.&lt;/p&gt;

&lt;p&gt;AWS still documents Reduced Redundancy Storage. The same page says not to use it. Standard is the replacement.&lt;/p&gt;

&lt;h2&gt;
  
  
  How teams usually get this wrong
&lt;/h2&gt;

&lt;p&gt;They set one class on the bucket in their head. Classes are per object. Lifecycle rules move prefixes as they age: Standard for 30 days, Standard-IA after that, Instant Retrieval or Flexible Retrieval a year later. You do not need a new bucket for each class.&lt;/p&gt;

&lt;p&gt;They forget that overwrite and delete count toward minimum duration. A "cheap" IA prefix that is replaced every deploy is not infrequent. It is Standard with extra fees.&lt;/p&gt;

&lt;p&gt;They treat Glacier as a folder. The object stays in S3. Flexible Retrieval and Deep Archive just will not &lt;code&gt;GET&lt;/code&gt; until &lt;code&gt;RestoreObject&lt;/code&gt; finishes.&lt;/p&gt;

&lt;p&gt;They optimize storage and ignore listing, monitoring, and restore. Intelligent-Tiering's per-object fee and Glacier's metadata bytes are real. They matter most when objects are small and numerous.&lt;/p&gt;

&lt;h2&gt;
  
  
  A default you can defend
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hot path, known: &lt;strong&gt;Standard&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Unknown, objects worth monitoring: &lt;strong&gt;Intelligent-Tiering&lt;/strong&gt;, automatic tiers only.&lt;/li&gt;
&lt;li&gt;Cold, must &lt;code&gt;GET&lt;/code&gt; now, multi-AZ: &lt;strong&gt;Standard-IA&lt;/strong&gt; or &lt;strong&gt;Instant Retrieval&lt;/strong&gt;, depending on how rare the read is.&lt;/li&gt;
&lt;li&gt;Cold, must &lt;code&gt;GET&lt;/code&gt; now, you can rebuild it: &lt;strong&gt;One Zone-IA&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Cold, you can wait hours: &lt;strong&gt;Flexible Retrieval&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Cold, you can wait a day, you will keep it for years: &lt;strong&gt;Deep Archive&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If that still feels like a guess, do not guess Glacier. Guess Intelligent-Tiering or Standard, then add a lifecycle when you have a real access log. The expensive class is the one that surprises you when someone finally opens the object.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3</category>
      <category>cloud</category>
      <category>storage</category>
    </item>
    <item>
      <title>O mesmo pedido chegou quatro vezes. O SQS não estava errado</title>
      <dc:creator>Rodolfo Henrique</dc:creator>
      <pubDate>Sun, 20 Sep 2026 21:09:28 +0000</pubDate>
      <link>https://dev.to/rodolfocoding/o-mesmo-pedido-chegou-quatro-vezes-o-sqs-nao-estava-errado-211m</link>
      <guid>https://dev.to/rodolfocoding/o-mesmo-pedido-chegou-quatro-vezes-o-sqs-nao-estava-errado-211m</guid>
      <description>&lt;p&gt;Este artigo é a continuação do lab de &lt;a href="https://medium.com/@rodolfo.coding/o-visibility-timeout-do-sqs-que-n%C3%A3o-processou-o-pedido-duas-vezes-2598624cadd8" rel="noopener noreferrer"&gt;visibility timeout no SQS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No primeiro lab eu tentei fabricar uma duplicata atrasando o relógio da fila. Não funcionou. A Lambda estende o visibility timeout enquanto processa. O alvo era o relógio. O alvo errado.&lt;/p&gt;

&lt;p&gt;O que ficou em aberto era outra coisa: o &lt;strong&gt;produtor&lt;/strong&gt;. E se eu mesmo mandar o mesmo pedido duas, quatro, dez vezes?&lt;/p&gt;

&lt;p&gt;Foi isso que eu fiz. Abaixo está o que subi, por que subi, e o que cada print mostra.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que eu queria descobrir
&lt;/h2&gt;

&lt;p&gt;O Amazon SQS (Simple Queue Service) é uma fila. Você coloca uma mensagem. Um consumidor tira a mensagem e trabalha.&lt;/p&gt;

&lt;p&gt;Fila &lt;strong&gt;standard&lt;/strong&gt; entrega &lt;em&gt;pelo menos uma vez&lt;/em&gt;. A documentação da Lambda diz a mesma coisa do outro lado: o event source mapping (a ligação fila → função) também processa pelo menos uma vez. O código precisa ser &lt;strong&gt;idempotente&lt;/strong&gt;: processar o mesmo pedido uma vez ou dez vezes deixa o mesmo resultado.&lt;/p&gt;

&lt;p&gt;Isso cobre a &lt;em&gt;mensagem&lt;/em&gt;. Não cobre o &lt;em&gt;pedido&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Imagine o checkout. O usuário clica em pagar. A rede falha. Ele clica de novo. O backend manda duas mensagens. O SQS aceita as duas. Cada uma ganha um &lt;code&gt;MessageId&lt;/code&gt; novo. Para a fila, são dois recados. Para o caixa, é o mesmo &lt;code&gt;ORDER-003&lt;/code&gt; de 150 reais.&lt;/p&gt;

&lt;p&gt;Pergunta do lab:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Se várias mensagens representam o mesmo pedido, o worker cobra uma vez ou cobra cada mensagem?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Dois identificadores. Não misture.
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Identificador&lt;/th&gt;
&lt;th&gt;Quem cria&lt;/th&gt;
&lt;th&gt;O que significa&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MessageId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O SQS, a cada &lt;code&gt;SendMessage&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Aquela cópia na fila&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;orderId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Você, no JSON do body&lt;/td&gt;
&lt;td&gt;O pedido de negócio&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;O &lt;code&gt;MessageId&lt;/code&gt; nomeia a mensagem. O &lt;code&gt;orderId&lt;/code&gt; nomeia o pedido. Idempotência neste lab trava o &lt;strong&gt;pedido&lt;/strong&gt;, não a mensagem.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que eu subi na AWS
&lt;/h2&gt;

&lt;p&gt;Tudo em &lt;code&gt;us-east-1&lt;/code&gt;. Sem fila FIFO. Sem gateway de pagamento. A "cobrança" é um log chamado &lt;code&gt;charge_applied&lt;/code&gt;. Se esse log aparece, o lab considera que o caixa rodou.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PowerShell (send.ps1)
        |
        v
SQS standard: aws-lab-sqs-idempotency
        |
        |  uma mensagem por invocação (batch size 1)
        v
Lambda: aws-lab-sqs-idempotency-worker
        |
        +-- CloudWatch Logs  (o que aconteceu)
        +-- DynamoDB         (a trava do orderId)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Peça&lt;/th&gt;
&lt;th&gt;Nome&lt;/th&gt;
&lt;th&gt;Para que serve&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fila&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws-lab-sqs-idempotency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Recebe as cópias do pedido&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Função&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws-lab-sqs-idempotency-worker&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lê a fila e "cobra"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tabela&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws-lab-sqs-idempotency&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Guarda o &lt;code&gt;orderId&lt;/code&gt; com um write condicional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logs&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/aws/lambda/aws-lab-sqs-idempotency-worker&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Evidência no Insights&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A função tem um interruptor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;IDEMPOTENCY=0&lt;/code&gt;: chegou mensagem, cobra. Sem perguntar nada.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IDEMPOTENCY=1&lt;/code&gt;: antes de cobrar, tenta gravar o &lt;code&gt;orderId&lt;/code&gt; no DynamoDB. Se o item já existe, não cobra.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por que batch size 1: cada mensagem vira uma invocação. Assim duas cópias podem correr ao mesmo tempo, em vez de cair no mesmo lote.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que a guarda não é um &lt;code&gt;if&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Este código parece idempotência e não é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Duas Lambdas leem ao mesmo tempo. As duas veem "não existe". As duas cobram. As duas gravam depois. A verificação e a reserva precisam ser &lt;strong&gt;a mesma operação&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No DynamoDB isso é um &lt;code&gt;PutItem&lt;/code&gt; com condição: "grave este &lt;code&gt;orderId&lt;/code&gt; só se ele ainda não existir".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ddb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PutItemCommand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CLAIMED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;messageId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;requestId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;claimedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;S&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;ConditionExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;attribute_not_exists(orderId)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Leitura do código, em português:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tente criar o item com PK &lt;code&gt;orderId&lt;/code&gt; e status &lt;code&gt;CLAIMED&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Se ninguém gravou essa PK ainda, você ganhou (&lt;code&gt;claim_won&lt;/code&gt;). Aí você cobra e marca &lt;code&gt;COMPLETED&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Se a PK já existe, o DynamoDB recusa com &lt;code&gt;ConditionalCheckFailedException&lt;/code&gt;. Você perdeu (&lt;code&gt;claim_lost&lt;/code&gt;), loga &lt;code&gt;skip_duplicate&lt;/code&gt; e &lt;strong&gt;não cobra&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;CLAIMED&lt;/code&gt; é reserva, não recibo. Eu não marco &lt;code&gt;COMPLETED&lt;/code&gt; antes de cobrar. Se eu marcasse "já processado" e a cobrança falhasse, o retry pularia um pedido que nunca saiu.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experimento 1: interruptor desligado
&lt;/h2&gt;

&lt;p&gt;O que eu fiz: subi o lab com &lt;code&gt;IDEMPOTENCY=0&lt;/code&gt; e mandei mensagens do mesmo pedido.&lt;/p&gt;

&lt;p&gt;Por que: para ver o comportamento sem trava. Se o worker cobra cada mensagem, o Insights tem que mostrar &lt;strong&gt;mais cobranças do que pedidos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O que eu vi no Logs Insights (Analytics de logs, visão &lt;strong&gt;Tabelas de pesquisa&lt;/strong&gt;), numa janela em que só existem três tipos de evento:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;eventType&lt;/th&gt;
&lt;th&gt;O que significa&lt;/th&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;process_start&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A Lambda começou a tratar a mensagem&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charge_applied&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;O caixa rodou&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;process_end&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A invocação terminou&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Não tem &lt;code&gt;claim_won&lt;/code&gt; nem &lt;code&gt;skip_duplicate&lt;/code&gt;. A guarda estava desligada.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjhiufa52pz5wjogr96dd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjhiufa52pz5wjogr96dd.png" alt="Quatro process_start, quatro charge_applied, quatro process_end. Sem eventos de claim." width="799" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Olhe a tabela de baixo: três linhas, todas com 4. Quatro invocações, quatro cobranças.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Depois eu contei só o efeito. A consulta pega &lt;code&gt;charge_applied&lt;/code&gt; e pergunta: quantas cobranças, quantos &lt;code&gt;orderId&lt;/code&gt; distintos, quantos &lt;code&gt;MessageId&lt;/code&gt; distintos?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fields @timestamp, @message
| filter @message like /"type":"charge_applied"/
| parse @message /"orderId":"(?&amp;lt;orderId&amp;gt;[^"]+)"/
| parse @message /"messageId":"(?&amp;lt;messageId&amp;gt;[^"]+)"/
| stats count(*) as charges, count_distinct(orderId) as pedidos, count_distinct(messageId) as mensagens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;charges&lt;/th&gt;
&lt;th&gt;pedidos&lt;/th&gt;
&lt;th&gt;mensagens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5cnvcc8kkyeo51qylxz5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5cnvcc8kkyeo51qylxz5.png" alt="4 charges, 1 pedido, 4 mensagens" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Quatro MessageId. Um orderId. Quatro cobranças. A fila tratou quatro recados. O caixa tratou o mesmo pedido quatro vezes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O mesmo número aparece em outro recorte da mesma consulta.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpusbrit3yd4f9rvp2zmr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpusbrit3yd4f9rvp2zmr.png" alt="Outro recorte da consulta de cobranças: de novo 4, 1 e 4" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para o SQS, o teste passou: quatro mensagens, quatro invocações, zero erro. Para o negócio, o cliente foi cobrado quatro vezes.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que idempotência quis dizer aqui
&lt;/h2&gt;

&lt;p&gt;Caminho que eu usei:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;orderId&lt;/code&gt; (o pedido) → mensagem (&lt;code&gt;MessageId&lt;/code&gt;) → Lambda → efeito (&lt;code&gt;charge_applied&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;Idempotente: aplicar &lt;code&gt;ORDER-003&lt;/code&gt; uma vez ou dez vezes deixa &lt;strong&gt;uma&lt;/strong&gt; cobrança de 150.&lt;/p&gt;

&lt;p&gt;Não é "o SQS joga a segunda mensagem fora". O SQS pode (e neste lab, deve) entregar as dez. O destino é que recusa o segundo efeito.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experimento 2: interruptor ligado, dez cópias
&lt;/h2&gt;

&lt;p&gt;O que eu fiz:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;destroy&lt;/code&gt; do lab antigo e &lt;code&gt;deploy&lt;/code&gt; de novo.&lt;/li&gt;
&lt;li&gt;Esperei a Lambda ficar ativa e o event source mapping em &lt;code&gt;Enabled&lt;/code&gt;, batch size 1.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.\set-idempotency.ps1 -Enabled 1&lt;/code&gt;. A variável da função ficou &lt;code&gt;IDEMPOTENCY=1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Mandei o mesmo pedido dez vezes:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\send.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-OrderId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ORDER-003&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Copies&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O body impresso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"ORDER-003"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"customerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"CUSTOMER-123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;150.00&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dez linhas. Dez &lt;code&gt;MessageId&lt;/code&gt; diferentes. &lt;code&gt;orderId=ORDER-003&lt;/code&gt; em todas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbc0c3jxu1nk3yx1nzdt4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbc0c3jxu1nk3yx1nzdt4.png" alt="Terminal: dez SendMessage de ORDER-003, cada um com MessageId novo" width="799" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;O que observar: a fila não juntou nada. Dez recados. Um pedido.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Por que dez, e não duas: para forçar várias invocações no mesmo &lt;code&gt;orderId&lt;/code&gt; com a guarda ligada.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que o Insights mostrou nesse pedido
&lt;/h2&gt;

&lt;p&gt;Filtrei &lt;code&gt;orderId = "ORDER-003"&lt;/code&gt;. Vieram 20 correspondências, nestes tipos:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;process_start&lt;/code&gt;, &lt;code&gt;claim_lost&lt;/code&gt;, &lt;code&gt;skip_duplicate&lt;/code&gt;, &lt;code&gt;process_end&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffe4krhj5e0pn0l0nvk18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffe4krhj5e0pn0l0nvk18.png" alt="Contagem só de ORDER-003: start, claim_lost, skip_duplicate, end. Vinte eventos." width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Leia assim: a mensagem chegou, tentou gravar a PK, perdeu, logou skip e encerrou. Sem nova cobrança nesse caminho.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A linha a linha é o mesmo filtro, evento por evento. Só &lt;code&gt;ORDER-003&lt;/code&gt;. &lt;code&gt;claim_lost&lt;/code&gt; e &lt;code&gt;skip_duplicate&lt;/code&gt; andam juntos. Os &lt;code&gt;MessageId&lt;/code&gt; mudam. O pedido não.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsvz40xyi7t9rt9qqu3m2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsvz40xyi7t9rt9qqu3m2.png" alt="Timeline ORDER-003: várias mensagens, o mesmo orderId, claim_lost e skip_duplicate" width="799" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  O que a tabela mostrou nesse pedido
&lt;/h2&gt;

&lt;p&gt;O &lt;code&gt;get-item&lt;/code&gt; de &lt;code&gt;ORDER-003&lt;/code&gt; devolveu &lt;strong&gt;um&lt;/strong&gt; item:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Campo&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;th&gt;Por que importa&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;orderId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ORDER-003&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A chave do pedido&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;COMPLETED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A reserva virou recibo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;messageId&lt;/code&gt; / &lt;code&gt;completedMessageId&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;73fca7ac-78e9-4ea4-a1bf-71a92e2fbda8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;É o envio 1/10 daquela corrida&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claimedAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2026-09-20T20:58:23.240Z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Quando a primeira cópia ganhou o PutItem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;completedAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2026-09-20T20:58:28.142Z&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cerca de 5 s depois. O worker espera 4 s (&lt;code&gt;WORK_MS=4000&lt;/code&gt;) e então marca completed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;scan&lt;/td&gt;
&lt;td&gt;1 item&lt;/td&gt;
&lt;td&gt;Não nasceu um item por mensagem&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A fila aceitou dez &lt;code&gt;MessageId&lt;/code&gt;. O destino ficou com um &lt;code&gt;ORDER-003&lt;/code&gt; em &lt;code&gt;COMPLETED&lt;/code&gt;. As cópias no Insights perderam o claim e não cobraram.&lt;/p&gt;

&lt;h2&gt;
  
  
  Os prints do grupo inteiro (com a guarda já visível)
&lt;/h2&gt;

&lt;p&gt;No log group sem filtrar &lt;code&gt;orderId&lt;/code&gt;, numa janela em que os eventos de claim já existem:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;eventType&lt;/th&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;process_end&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;charge_applied&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;skip_duplicate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claim_lost&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;process_start&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;claim_won&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1a6r0ahcjn607ssa68ea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1a6r0ahcjn607ssa68ea.png" alt="Grupo inteiro: um claim_won, dois claim_lost, um skip_duplicate, cinco charge_applied" width="799" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Isso mostra a guarda em ação no grupo: alguém ganhou o claim, alguém perdeu, alguém pulou a cobrança.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A consulta de cobranças no grupo inteiro, recorte mais largo: 7 charges, 3 pedidos, 7 mensagens. São vários &lt;code&gt;orderId&lt;/code&gt; no mesmo log group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpr8wscebem4ma2syu5yk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpr8wscebem4ma2syu5yk.png" alt="Agregado do grupo: 7 charges, 3 pedidos, 7 mensagens" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lado a lado
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Sem guarda&lt;/th&gt;
&lt;th&gt;Com guarda, pedido &lt;code&gt;ORDER-003&lt;/code&gt;
&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;O que eu mandei&lt;/td&gt;
&lt;td&gt;várias mensagens do mesmo pedido&lt;/td&gt;
&lt;td&gt;10 &lt;code&gt;SendMessage&lt;/code&gt; com o mesmo &lt;code&gt;ORDER-003&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O que a fila fez&lt;/td&gt;
&lt;td&gt;aceitou cada &lt;code&gt;MessageId&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;aceitou cada &lt;code&gt;MessageId&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O que o Insights mostrou&lt;/td&gt;
&lt;td&gt;4 start, 4 charge, 4 end&lt;/td&gt;
&lt;td&gt;20 eventos de start / &lt;code&gt;claim_lost&lt;/code&gt; / &lt;code&gt;skip_duplicate&lt;/code&gt; / end&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O que a tabela mostrou&lt;/td&gt;
&lt;td&gt;a guarda estava desligada&lt;/td&gt;
&lt;td&gt;um item &lt;code&gt;ORDER-003&lt;/code&gt; / &lt;code&gt;COMPLETED&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Efeito no caixa&lt;/td&gt;
&lt;td&gt;4 cobranças para 1 &lt;code&gt;orderId&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;um pedido reservado e concluído; as cópias visíveis não cobraram&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A fila fez o trabalho dela nas duas vezes. A diferença está no destino.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que este lab não promete
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SQS standard &lt;strong&gt;não&lt;/strong&gt; vira exactly-once porque você usou Lambda. Continua at-least-once.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;if (exists) return&lt;/code&gt; &lt;strong&gt;não&lt;/strong&gt; é a guarda. Duas leituras ao mesmo tempo furam isso.&lt;/li&gt;
&lt;li&gt;FIFO com &lt;code&gt;MessageDeduplicationId&lt;/code&gt; ajuda a não &lt;em&gt;enviar&lt;/em&gt; a mesma mensagem de novo por alguns minutos. Não substitui a tabela no destino quando &lt;strong&gt;você quer&lt;/strong&gt; enfileirar o mesmo pedido várias vezes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O que eu levo
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;MessageId&lt;/code&gt; é a mensagem. &lt;code&gt;orderId&lt;/code&gt; é o pedido. A trava vai no pedido.&lt;/li&gt;
&lt;li&gt;Sem guarda, quatro mensagens do mesmo &lt;code&gt;orderId&lt;/code&gt; foram quatro &lt;code&gt;charge_applied&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A reserva é o &lt;code&gt;PutItem&lt;/code&gt; com &lt;code&gt;attribute_not_exists(orderId)&lt;/code&gt;. Quem perde loga &lt;code&gt;claim_lost&lt;/code&gt; e &lt;code&gt;skip_duplicate&lt;/code&gt; e não cobra.&lt;/li&gt;
&lt;li&gt;Idempotência neste desenho é: a fila pode entregar dez vezes; o caixa do pedido roda uma.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>aws</category>
      <category>sqs</category>
      <category>dynamodb</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
