<?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>Forem: Giovana Armani</title>
    <description>The latest articles on Forem by Giovana Armani (@giarmani).</description>
    <link>https://forem.com/giarmani</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3702681%2F9e12f714-2b0b-4eee-bae7-8621caf4a8a0.png</url>
      <title>Forem: Giovana Armani</title>
      <link>https://forem.com/giarmani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/giarmani"/>
    <language>en</language>
    <item>
      <title>Lambda Durable Functions: Como construir aplicações multi-etapas com um único serviço</title>
      <dc:creator>Giovana Armani</dc:creator>
      <pubDate>Wed, 08 Apr 2026 12:31:20 +0000</pubDate>
      <link>https://forem.com/aws/lambda-durable-functions-como-construir-aplicacoes-multi-etapas-com-um-unico-servico-318c</link>
      <guid>https://forem.com/aws/lambda-durable-functions-como-construir-aplicacoes-multi-etapas-com-um-unico-servico-318c</guid>
      <description>&lt;p&gt;Sempre quis rodar processos longos em uma função Lambda sem se preocupar com o limite de 15 minutos? E executar processos com múltiplos passos sem sair do lugar? Não diga mais nada! Conheça AWS Lambda Durable Functions...&lt;/p&gt;

&lt;h2&gt;
  
  
  Complexidade de workflows: um problema conhecido
&lt;/h2&gt;

&lt;p&gt;Quem já trabalhou com sistemas baseados em workflows sabe que é uma tarefa que pode ficar complexa bem rapidamente. &lt;/p&gt;

&lt;p&gt;Você começa definindo a sequência de instruções que precisa seguir. É fácil pensar no clássico caminho feliz quando tudo dá certo, mas a coisa começa a complicar quando lembramos que sistemas falham...&lt;/p&gt;

&lt;p&gt;A cada passo, você precisa registrar o estado da sua aplicação para saber exatamente o que já foi executado. Se algo falha, você precisa garantir que é seguro dar um retry. Passos já completos devem ser pulados e se forem reexecutados, devem produzir o mesmo resultado sempre. Essa propriedade se chama &lt;strong&gt;idempotência&lt;/strong&gt;. Ela que garante que uma re-execução não vai causar duplicações ou inconsistências no sistema.&lt;/p&gt;

&lt;p&gt;Existem serviços de orquestração de workflows que simplificam esse processo de maneira visual, como o AWS Step Functions. Mas esses também trazem seus desafios porque o lugar onde os passos são declarados é diferente de onde são implementados. A definição do workflow fica em um arquivo JSON ou YAML e a implementação mora no código. Isso torna mais difícil testar o caminho inteiro e as várias possibilidades já que vemos a lógica toda distribuída.&lt;/p&gt;

&lt;p&gt;Isso tudo sem contar a complexidade de administrar vários serviços separados. Quem nunca se perdeu ao tentar administrar e monitorar várias funções Lambda ao mesmo tempo que atire a primeira pedra...&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.amazonaws.com%2Fuploads%2Farticles%2F8byqlz51hnqik8ursys3.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.amazonaws.com%2Fuploads%2Farticles%2F8byqlz51hnqik8ursys3.png" alt="Desenvolvedor estressado administrando várias funções Lambda" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lambda Durable Functions traz uma alternativa para criar e administrar workflows de maneira serverless de forma simplificada dentro do próprio código, centralizando tudo em uma mesma função.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é AWS Lambda Durable Functions?
&lt;/h2&gt;

&lt;p&gt;Lambda Durable Functions é uma funcionalidade do &lt;a href="https://aws.amazon.com/pt/pm/lambda/?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt;. Ela permite criar e executar workflows dentro de uma função lambda diretamente pelo código da função. No momento, a funcionalidade está disponível para Node.js a partir da versão 22.x e Python a partir da versão 3.13. A funcionalidade também está em fase de &lt;a href="https://aws.amazon.com/pt/about-aws/whats-new/2026/02/lambda-durable-execution-java-preview/?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Developer Preview para Java&lt;/a&gt;, o que significa que tem suporte para a linguagem no SDK, mas só pode ser criada através de uma imagem de contêiner. &lt;/p&gt;

&lt;p&gt;Sendo uma funcionalidade do AWS Lambda, Durable Functions naturalmente entra como parte do &lt;a href="https://dev.to/giarmani/a-verdade-oculta-por-tras-do-serverless-55f7"&gt;universo serverless&lt;/a&gt;. Isso significa que podemos implementar as funcionalidades de um workflow como checkpoints, retries, pausa e retorno sem administrar instâncias de servidores!&lt;/p&gt;

&lt;h2&gt;
  
  
  Como criar uma Durable Function
&lt;/h2&gt;

&lt;p&gt;Para ter uma função Lambda com Durable Functions, é preciso habilitar essa funcionalidade desde sua criação. Não é possível alterar uma função já existente para ser uma função durável. Conseguimos criá-la pelo console, pela CLI ou usando infraestrutura como código. &lt;/p&gt;

&lt;p&gt;No console, isso é feito habilitando a execução durável na página de criação como demonstrado abaixo.&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fqewd30fevvajvtzp80a4.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.amazonaws.com%2Fuploads%2Farticles%2Fqewd30fevvajvtzp80a4.png" alt="Criação de Lambda Durable Function pelo console da AWS" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para criar através da CLI, rodamos o comando de criação com o atributo durable-config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws lambda create-function &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; minha-funcao-duravel &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--runtime&lt;/span&gt; python3.14 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt; arn:aws:iam::&amp;lt;numero_da_conta_aws&amp;gt;:role/minha-funcao-duravel-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--handler&lt;/span&gt; lambda_function.lambda_handler &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--zip-file&lt;/span&gt; fileb://function.zip &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--durable-config&lt;/span&gt; &lt;span class="s1"&gt;'{"ExecutionTimeout": 3600, "RetentionPeriodInDays": 7}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse atributo aceita dois parâmetros opcionais de configuração da Durable Function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ExecutionTimeout - tempo máximo em segundos que a execução durável inteira pode durar, incluindo tempos de pausa e retry. O tempo máximo é de 1 ano&lt;/li&gt;
&lt;li&gt;RetentionPeriodInDays - número de dias que o histórico das execuções duráveis são armazenados depois de serem finalizados&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Observação:&lt;/em&gt; o comando acima de criação de função Lambda é um exemplo ilustrativo. Para executá-lo com sucesso, seria preciso criar a role do IAM chamada "minha-funcao-duravel-role" e ter um zip chamado "function.zip" contendo o código da função.&lt;/p&gt;

&lt;p&gt;De forma parecida, podemos criar Lambda Durable Functions usando infraestrutura como código. Fazemos isso através do CloudFormation, um serviço da AWS que permite criar e gerenciar sua infraestrutura na nuvem utilizando templates JSON ou YAML. Existem ainda ferramentas como AWS CDK e Terraform que auxiliam nessa criação permitindo usar linguagens de programação. Em um template de CloudFormation, a Durable Function também apresenta o atributo de DurableConfig:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MyDurableFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Lambda::Function&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;FunctionName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;minha-funcao-duravel&lt;/span&gt;
      &lt;span class="na"&gt;Runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python3.14&lt;/span&gt;
      &lt;span class="na"&gt;Handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lambda_function.lambda_handler&lt;/span&gt;
      &lt;span class="na"&gt;Code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;ZipFile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fileb://function.zip&lt;/span&gt;
      &lt;span class="na"&gt;DurableConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;ExecutionTimeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3600&lt;/span&gt;
        &lt;span class="na"&gt;RetentionPeriodInDays&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Como funciona?
&lt;/h2&gt;

&lt;p&gt;Vamos imaginar como exemplo uma aplicação de criação de ordem de compra. Um funcionário cria a ordem de compra, então o sistema verifica no inventário se os itens solicitados estão disponíveis. Caso estejam, alguns gerentes responsáveis são notificados para revisar e aprovar a compra e, se aprovarem, a ordem é confirmada. &lt;/p&gt;

&lt;p&gt;Quando uma função Lambda está habilitada como uma &lt;strong&gt;Durable Function&lt;/strong&gt;, dizemos que ela permite uma &lt;strong&gt;durable execution&lt;/strong&gt; (execução durável) e cada etapa do workflow é um &lt;strong&gt;durable step&lt;/strong&gt; (passo durável). Isso significa que a função consegue "lembrar" o estado em que estava no caso de falhas ou pausas e retomar a execução a partir desse ponto.&lt;/p&gt;

&lt;p&gt;Veja no diagrama abaixo como poderíamos representar os passos da aplicação de ordem de compra:&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.amazonaws.com%2Fuploads%2Farticles%2Fj4cdr4pjp50j0riidf71.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.amazonaws.com%2Fuploads%2Farticles%2Fj4cdr4pjp50j0riidf71.png" alt="Diagrama mostrando passos do workflow de ordem de compra" width="800" height="1446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Existem alguns conceitos fundamentais para administração de workflows que aparecem nas Durable Functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoint e replay
&lt;/h3&gt;

&lt;p&gt;Veja abaixo o nosso exemplo como estrutura de um código de uma Lambda Durable Function em Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@durable_step&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StepContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Implementação da criação de ordem
&lt;/span&gt;
&lt;span class="nd"&gt;@durable_step&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_inventory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StepContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Implementação da checagem de inventário
&lt;/span&gt;
&lt;span class="nd"&gt;@durable_step&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;notify_approver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StepContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;callback_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;approver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Implementação da notificação de gestores
&lt;/span&gt;
&lt;span class="nd"&gt;@durable_step&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;confirm_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;step_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StepContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Implementação da confirmação de ordem
&lt;/span&gt;
&lt;span class="nd"&gt;@durable_execution&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DurableContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Chamada e orquestração dos steps
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note que o handler da função Lambda, ou seja, seu ponto de entrada, é anotado com &lt;code&gt;@durable_execution&lt;/code&gt;. Cada um dos steps é anotado com &lt;code&gt;@durable_step&lt;/code&gt;. Após a execução de cada um dos steps, é feito um &lt;strong&gt;checkpoint&lt;/strong&gt; automático que registra o resultado de cada passo. Caso a função seja pausada (veremos isso numa próxima seção) e retome, ela será reexecutada do início, steps já completos serão pulados e a função usará os resultados já armazenados. Chamamos essa retomada de &lt;strong&gt;replay&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retry
&lt;/h3&gt;

&lt;p&gt;Diferentemente do replay que acontece quando o código é pausado, o &lt;strong&gt;retry&lt;/strong&gt; acontece na falha. Quando uma exceção ocorre dentro de um step, ele será &lt;a href="https://github.com/aws/aws-durable-execution-sdk-python/blob/main/docs/advanced/error-handling.md?plain=1#L320" rel="noopener noreferrer"&gt;automaticamente retentado&lt;/a&gt;. É possível também declarar sua própria estratégia de retry como eu faço abaixo no step de criação de ordem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@durable_execution&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DurableContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Recebe dados da ordem através do evento enviado para a função
&lt;/span&gt;    &lt;span class="n"&gt;order_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;retry_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RetryStrategyConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;backoff_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Configuração personalizada de retry
&lt;/span&gt;    &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;create_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;StepConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retry_strategy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;create_retry_strategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;retry_config&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;h3&gt;
  
  
  Wait
&lt;/h3&gt;

&lt;p&gt;É possível fazer com que sua função espere um determinado tempo antes de executar uma próxima instrução. No nosso exemplo, vamos imaginar que queremos que a função espere um tempo depois da criação da ordem para checar o inventário.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@durable_execution&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DurableContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;order_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;create_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_minutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# Espera por 5 minutos
&lt;/span&gt;
    &lt;span class="n"&gt;inventory_check&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;check_inventory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;# Restante da implementação
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Durante o tempo de espera, a função está pausada, então não serão feitas cobranças por esse período. O timeout máximo de uma invocação individual de uma função Lambda continua sendo 15 minutos, mas a durable execution pode durar até 1 ano!&lt;/p&gt;

&lt;h3&gt;
  
  
  Callback
&lt;/h3&gt;

&lt;p&gt;Além de querer pausar nossa execução por um tempo específico, podemos querer pausar até obter uma resposta de um serviço externo ou até mesmo de um usuário, como é o caso da aprovação dos gestores no nosso exemplo. Essa estratégia de resposta assíncrona é chamada de &lt;strong&gt;callback&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Quando chamamos a função &lt;code&gt;create_callback&lt;/code&gt; do SDK, geramos um &lt;strong&gt;identificador único&lt;/strong&gt; (o &lt;code&gt;callback_id&lt;/code&gt;) que enviamos para o sistema ou pessoa que precisa responder. A função então pausa no &lt;code&gt;callback.result()&lt;/code&gt; sem consumir recursos até que a resposta chegue. Portanto, assim como no caso do wait, não recebemos cobrança durante esse período de espera.&lt;/p&gt;

&lt;p&gt;Vamos ver como ficaria a aprovação de um único gestor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@durable_execution&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DurableContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Chamada de passos anteriores
&lt;/span&gt;    &lt;span class="n"&gt;approvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approvers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# [{"name": "Ana"}, {"name": "Júlia"}, {"name": "Bruno"}]
&lt;/span&gt;
    &lt;span class="c1"&gt;# Cria o callback com timeout de 24 horas
&lt;/span&gt;    &lt;span class="n"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approval-manager&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;CallbackConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_hours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;notify_approver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;callback_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;approvers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

    &lt;span class="n"&gt;approval_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Restante da implementação
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para responder, o sistema ou pessoa deve chamar a API &lt;code&gt;SendDurableExecutionCallbackSuccess&lt;/code&gt; do Lambda. O gestor poderia usar um outro sistema com sua própria função Lambda que chama essa API do sistema de criação de ordem para notificar a aprovação. Em código teríamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;lambda_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lambda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;callback_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;callback_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;approved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Mandando callback de sucesso
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;approved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;lambda_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_durable_execution_callback_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;CallbackId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;callback_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approved&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;: true}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Mandando callback de erro
&lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;lambda_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_durable_execution_callback_failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;CallbackId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;callback_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ErrorType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Rejected&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ErrorMessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Approver rejected the order&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Callback sent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Parallel
&lt;/h3&gt;

&lt;p&gt;Vimos como configuraríamos para esperar a resposta de um gestor, mas no nosso exemplo, a ordem de compra precisa ser aprovada por vários gestores. Ao invés de enviar um callback de cada vez e esperar sequencialmente, podemos usar &lt;code&gt;context.parallel&lt;/code&gt; para enviar todos ao mesmo tempo. Isso gera uma &lt;strong&gt;branch&lt;/strong&gt; (ramificação) para cada chamada que roda de forma independente com seu próprio checkpoint.&lt;/p&gt;

&lt;p&gt;No código abaixo, cada gestor recebe seu próprio callback e a função espera todas as respostas chegarem antes de continuar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@durable_execution&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DurableContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Chamada de passos anteriores
&lt;/span&gt;
    &lt;span class="n"&gt;approvers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approvers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# [{"name": "Ana"}, {"name": "Júlia"}, {"name": "Bruno"}]
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;request_approval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;approver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DurableContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Cria um callback para cada gestor
&lt;/span&gt;        &lt;span class="n"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approval-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;approver&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;CallbackConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_hours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;heartbeat_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_hours&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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="c1"&gt;# Notifica o gestor com o callback_id
&lt;/span&gt;        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;step&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;notify_approver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;callback_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;approver&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c1"&gt;# Pausa até o gestor responder
&lt;/span&gt;        &lt;span class="n"&gt;approval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;approver&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;approver&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;decision&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;approval&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Executa todas as aprovações em paralelo
&lt;/span&gt;    &lt;span class="n"&gt;approval_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parallel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;approver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;request_approval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;approver&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;approvers&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;send-approvals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Restante da implementação
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se Ana responder em 5 minutos e Bruno demorar 2 horas, a função continua pausada sem custo até que todos respondam. Cada branch tem seus próprios checkpoints, então se uma falhar, as outras não são afetadas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cálculo de preço
&lt;/h2&gt;

&lt;p&gt;A cobrança de uma Durable Function é composta por quatro componentes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cobranças padrão do Lambda&lt;/strong&gt; — as mesmas cobranças de requests e duração de qualquer função Lambda: $0.20 a cada 1 milhão de requisições mais o valor por duração das execuções que varia de acordo com a arquitetura da função ($0.0000166667 por GB-segundo para arquitetura x86 e $0.0000133334 por GB-segundo para ARM/Graviton2) Isso inclui sub-invocações geradas por replays. Durante operações de wait ou callback, funções on-demand não geram cobrança de duração já que a execução está suspensa.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Operações duráveis&lt;/strong&gt; — cada operação durável (iniciar uma execução, completar um step, criar um wait, etc.) é cobrada individualmente. O preço na região US East (N. Virginia) é de $8.00 por milhão de operações.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dados escritos&lt;/strong&gt; — os dados persistidos pelos checkpoints (payloads de steps, waits, callbacks) são cobrados por GB escrito. O preço é de $0.25 por GB.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Retenção de dados&lt;/strong&gt; — os dados dos checkpoints são armazenados durante a execução e após sua finalização. A cobrança é de $0.15 por GB-mês, proporcional ao tempo de armazenamento. O período de retenção após a conclusão é configurável de 1 a 90 dias (padrão: 14 dias).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Para mais informações sobre preço, consulte a &lt;a href="https://aws.amazon.com/lambda/pricing/?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;página de preços do AWS Lambda&lt;/a&gt; e a &lt;a href="https://calculator.aws/#/createCalculator/Lambda?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;calculadora de preços da AWS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diferença entre Lambda Durable Functions e Step Functions
&lt;/h2&gt;

&lt;p&gt;Se você já conhece a AWS, provavelmente está se perguntando: "mas isso não é o que o Step Functions faz?". Boa pergunta! Os dois serviços resolvem o mesmo problema, mas de formas bem diferentes.&lt;/p&gt;

&lt;p&gt;A principal diferença está em &lt;em&gt;onde&lt;/em&gt; o workflow é definido. No Step Functions, você declara o fluxo usando um arquivo JSON chamado ASL (Amazon States Language). Cada estado e transição é definido nesse arquivo, separado do código que executa a lógica. Cada passo do Step Functions pode chamar uma função Lambda, outro serviço de compute, ou até mesmo fazer uma chamada de serviço diretamente, como chamar o Dynamo ou uma fila, por exemplo.&lt;/p&gt;

&lt;p&gt;Já com Durable Functions, o workflow inteiro mora no código da função Lambda. Você escreve a sequência de passos como código normal e o SDK cuida do resto.&lt;/p&gt;

&lt;p&gt;Ambos são modelos de &lt;strong&gt;orquestração&lt;/strong&gt;, ou seja, existe um coordenador central que controla o fluxo e sabe qual é o próximo passo. A diferença é que no Step Functions o orquestrador é a máquina de estados que é demonstrada de forma visual no console da AWS e no Durable Functions o orquestrador é o próprio código do handler.&lt;/p&gt;

&lt;p&gt;Veja na tabela abaixo um comparativo entre os dois serviços:&lt;/p&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;Step Functions&lt;/th&gt;
&lt;th&gt;Durable Functions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Definição do workflow&lt;/td&gt;
&lt;td&gt;Declarativa (ASL JSON/YAML), separada do código&lt;/td&gt;
&lt;td&gt;Imperativa, dentro do código da função&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gerenciamento de estado&lt;/td&gt;
&lt;td&gt;Gerenciado pelo serviço através de transições de estado&lt;/td&gt;
&lt;td&gt;Gerenciado pelo SDK através de checkpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visibilidade da execução&lt;/td&gt;
&lt;td&gt;Console visual com diagrama do fluxo e histórico de execução&lt;/td&gt;
&lt;td&gt;Aba "Durable executions" no console do Lambda + Logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Integrações nativas&lt;/td&gt;
&lt;td&gt;Mais de 200 integrações diretas com serviços AWS sem precisar de código&lt;/td&gt;
&lt;td&gt;Integrações feitas via SDK dentro de steps no código&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Melhor para&lt;/td&gt;
&lt;td&gt;Fluxos complexos com muitas integrações AWS e equipes que preferem workflows visuais, como equipes voltadas a negócios&lt;/td&gt;
&lt;td&gt;Fluxos com foco no programa, equipes técnicas que preferem manter tudo no código&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Uma vantagem prática do Durable Functions é que como tudo está no código, fica mais fácil testar o fluxo inteiro localmente. Com Step Functions, testar o workflow completo geralmente exige deployar a máquina de estados e as funções Lambda separadamente, o que adiciona complexidade no ciclo de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Por outro lado, Step Functions brilha quando você precisa de integrações diretas com serviços AWS sem escrever código para cada chamada, ou quando a visibilidade visual do fluxo é importante para a equipe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Nesse artigo, vimos como Lambda Durable Functions permite construir workflows multi-etapas diretamente no código de uma função Lambda. Passamos pelos conceitos de durable execution, steps, checkpoints e replay, e vimos na prática como funcionalidades como wait, callbacks e execução paralela se traduzem para código em um exemplo de criação de ordem de compra.&lt;/p&gt;

&lt;p&gt;Também entendemos como Durable Functions se compara ao Step Functions: ambos orquestram processos, mas com modelos mentais diferentes. &lt;/p&gt;

&lt;p&gt;Como próximo passo, que tal experimentar reproduzir o exemplo desse artigo na sua própria conta? Você pode testar usando uma &lt;a href="https://builder.aws.com/content/2lYwQJ47Sq8C76VkFUDisXB7VnN/secure-foundation-setting-up-your-aws-free-tier-account?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;conta Free Tier da AWS&lt;/a&gt;! Ela permite que você explore serviços AWS com até 200 dólares de créditos por um período de 6 meses. Você não será cobrado a não ser que explicitamente escolha trocar de plano. Se quiser começar a pensar em problemas de fim a fim e criar sistemas serverless, deixo aqui ainda &lt;a href="https://dev.to/aws/seu-primeiro-sistema-serverless-com-aws-lambda-7ai"&gt;esse artigo&lt;/a&gt; para criar seu primeiro sistema serverless com AWS Lambda.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>lambda</category>
      <category>development</category>
      <category>tooling</category>
    </item>
    <item>
      <title>JavaScript e SDK: Como sua aplicação web pode falar com a nuvem</title>
      <dc:creator>Giovana Armani</dc:creator>
      <pubDate>Thu, 26 Mar 2026 19:29:54 +0000</pubDate>
      <link>https://forem.com/aws/javascript-e-sdk-como-sua-aplicacao-web-pode-falar-com-a-nuvem-cn4</link>
      <guid>https://forem.com/aws/javascript-e-sdk-como-sua-aplicacao-web-pode-falar-com-a-nuvem-cn4</guid>
      <description>&lt;p&gt;Em artigos passados, falei sobre &lt;a href="https://dev.to/aws/sdk-as-ferramentas-para-seu-codigo-se-conectar-com-o-mundo-5d0e"&gt;o que é SDK e por que ele é importante&lt;/a&gt; e &lt;a href="https://dev.to/aws/seu-primeiro-sistema-serverless-com-aws-lambda-7ai"&gt;construímos uma aplicação back-end&lt;/a&gt; para conversão de documentos usando o SDK da AWS. Vamos usar o SDK mais uma vez, mas agora para construir nosso front-end!&lt;/p&gt;




&lt;h2&gt;
  
  
  O que é SDK mesmo?
&lt;/h2&gt;

&lt;p&gt;Podemos pensar SDK (Software Development Kit) como uma caixa de ferramentas para construir aplicações sobre uma plataforma, sistema operacional ou linguagem de programação. Ele pode incluir bibliotecas, APIs, documentação, exemplos de código, debuggers, entre outras coisas. Caso queira saber mais sobre SDK e sua diferença para APIs e bibliotecas, veja &lt;a href="https://dev.to/aws/sdk-as-ferramentas-para-seu-codigo-se-conectar-com-o-mundo-5d0e"&gt;esse artigo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;O SDK da AWS para JavaScript permite fácil acesso a serviços da AWS a partir de seu código JS. Você verá como com algumas importações e comandos rápidos podemos conversar diretamente com a nuvem!&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.amazonaws.com%2Fuploads%2Farticles%2Fzbggmlowz77qwyei0qpq.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.amazonaws.com%2Fuploads%2Farticles%2Fzbggmlowz77qwyei0qpq.png" alt="Diagrama ilustrando código javascript usando o SDK para acessar a nuvem" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tudo que construiremos nesse tutorial, assim como o tutorial do back-end, pode ser reproduzido com uma conta Free Tier da AWS. Com ela, você ganha 100 dólares em créditos na conta e pode ganhar até 100 dólares adicionais ao explorar os diferentes serviços da AWS e não será cobrado a não ser que explicitamente escolha trocar de plano. Se quiser saber mais sobre como criar sua conta e as melhores configurações de segurança, veja &lt;a href="https://builder.aws.com/content/2lYwQJ47Sq8C76VkFUDisXB7VnN/secure-foundation-setting-up-your-aws-free-tier-account?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;esse artigo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que vamos construir
&lt;/h2&gt;

&lt;p&gt;No nosso backend, temos uma função Lambda que converte arquivos CSV para JSON. Ela é acionada quando colocamos um arquivo no &lt;a href="https://docs.aws.amazon.com/pt_br/AmazonS3/latest/userguide/Welcome.html?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;bucket S3&lt;/a&gt; de input e coloca os arquivos convertidos em um outro bucket do S3 de output. Como queremos fazer o front-end para essa aplicação, vamos construir uma tela que rodará no navegador. Ela será dividida em duas partes: uma seção para fazer o upload de arquivos CSV e outra para o download dos arquivos JSON. &lt;/p&gt;

&lt;h2&gt;
  
  
  Primeiros passos: rodando a página web
&lt;/h2&gt;

&lt;p&gt;Para esse projeto, vamos usar &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt;, uma biblioteca do JavaScript para criação de interfaces. Para isso, é preciso ter o node.js. Caso não tenha node na sua máquina, comece baixando no &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;site oficial&lt;/a&gt;. Selecione "Get Node.js" para baixar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gi-armani/CSV-JSON-Converter-sample-for-aws-SDK" rel="noopener noreferrer"&gt;Nesse repositório&lt;/a&gt; você encontrará o código completo do front-end na pasta "front", assim como o back-end que já construímos. Para começar a reproduzir a aplicação, clone ele para editar o código. Siga os passos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Crie uma pasta no seu computador para o projeto&lt;/li&gt;
&lt;li&gt;No terminal, navegue até a pasta criada através do comando &lt;code&gt;cd &amp;lt;caminho-ate-a-pasta&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clone o repositório com o comando &lt;code&gt;git clone https://github.com/gi-armani/CSV-JSON-Converter-sample-for-aws-SDK&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Para rodar a aplicação, navegue até a raiz do projeto com o comando &lt;code&gt;cd &amp;lt;caminho-ate-a-pasta-criada&amp;gt;/CSV-JSON-Converter-sample-for-aws-SDK/front&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Execute &lt;code&gt;npm install&lt;/code&gt; para instalar as dependências e &lt;code&gt;npm start&lt;/code&gt; para iniciar&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Você deverá ver uma mensagem parecida com a mensagem abaixo:&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.amazonaws.com%2Fuploads%2Farticles%2Fc9g7hxw8j7npmhaphl2m.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.amazonaws.com%2Fuploads%2Farticles%2Fc9g7hxw8j7npmhaphl2m.png" alt="Mensagem de sucesso da aplicação React iniciada" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora você pode abrir &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt; no seu navegador de preferência e ver os elementos visuais da aplicação. Lembre-se que ela ainda não está conectada na nuvem, mas vamos cuidar disso!&lt;/p&gt;

&lt;h3&gt;
  
  
  Entendendo a estrutura da página
&lt;/h3&gt;

&lt;p&gt;Quando iniciamos um projeto React, o principal arquivo da aplicação estará localizado em &lt;code&gt;CSV-JSON-Converter-sample-for-aws-SDK/front/src/App.js&lt;/code&gt; que contém a seguinte estrutura:&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="c1"&gt;// importação de bibliotecas, imagens e outros elementos&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;logo&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./logo.svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Aqui colocamos a lógica (variáveis e funções que precisaremos usar)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// Aqui estarão os diferentes elementos do site, declarados em componentes similares ao html&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O trecho de código acima tem indicativos de onde estarão os nossos elementos visuais (textos, inputs, botões, etc) e onde estará a lógica dos processos. Veja que no código que você clonou tudo isso já está criado, mas ainda vamos precisar substituir algumas constantes para conectar com a nuvem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configurando permissões
&lt;/h2&gt;

&lt;p&gt;Pausando um pouco no código e indo para a conexão com a nuvem, precisamos configurar permissões para nosso código conseguir acessar os arquivos. Agora vamos conectar o front-end com o back-end que criamos anteriormente. Caso você não tenha os buckets do S3 e a função Lambda na sua conta, recomendo criá-los primeiro usando as instruções do &lt;a href="https://dev.to/aws/seu-primeiro-sistema-serverless-com-aws-lambda-7ai"&gt;artigo anterior&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Para isso, vamos usar o IAM (AWS Identity and Access Management). Esse é um serviço da AWS que permite controlar acesso a permissões dentro da sua conta. Se quiser entender mais sobre como funciona o IAM e os diferentes tipos de permissão, veja &lt;a href="https://builder.aws.com/content/35z2TS8V8AIpEqHm1bdM7LLa2hz/desmistificando-permissoes-na-aws?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;esse artigo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Na minha conta AWS, estou na região de us-west-2 (Estados Unidos Oregon). É importante criar todos os seus recursos na mesma região para evitar problemas de comunicação entre eles. Você pode identificar a região que você está a qualquer momento no menu superior da conta ao lado do nome e número da conta.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando a política de acesso ao S3
&lt;/h3&gt;

&lt;p&gt;Vamos começar criando a política de acesso, ou seja, o documento que diz o que é permitido fazer e onde.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No console da AWS da sua conta Free Tier, navegue até a página do IAM e selecione "Políticas" no menu da esquerda&lt;/li&gt;
&lt;li&gt;Clique em "Criar política"&lt;/li&gt;
&lt;li&gt;No canto superior direito do editor de políticas, selecione a opção JSON e cole o conteúdo abaixo. Não se esqueça de substituir os locais indicados em "Resource" com os nomes dos seus buckets
&lt;/li&gt;
&lt;/ol&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="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowWriteInput"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::&amp;lt;NOME-DO-SEU-BUCKET-DE-INPUT&amp;gt;/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowReadOutput"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::&amp;lt;NOME-DO-SEU-BUCKET-DE-OUTPUT&amp;gt;/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AllowListOutput"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListBucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::gio-csv-converter-output"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&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;Aqui temos uma política que permite subir arquivos no bucket de input (operação PutObject) e ler arquivos do bucket de output (operação GetObject). Temos também uma última permissão que permite listar os objetos de um bucket (operação ListBucket). Essa última é importante porque caso a conversão do json ainda não tenha sido terminada, fará com que o S3 retorne um erro mais amigável dizendo que o arquivo ainda não existe. Sem essa permissão, o S3 retornaria um erro de acesso negado.&lt;/p&gt;

&lt;p&gt;Na opção "Visual" do editor de políticas, é possível construir essa mesma política de forma interativa selecionando os serviços e as operações que serão usadas (deixo para a curiosidade de quem quiser explorar 😉). &lt;/p&gt;

&lt;p&gt;Para terminar a criação, basta selecionar "Próximo", dar um nome à sua política na próxima página (chamei a minha de "jsWebClientS3Access") e então selecionar "Criar política" no canto inferior direito.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando um identity pool
&lt;/h3&gt;

&lt;p&gt;Para essa parte, vamos usar o &lt;a href="https://docs.aws.amazon.com/pt_br/cognito/latest/developerguide/what-is-amazon-cognito.html?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Cognito&lt;/a&gt;, um serviço da AWS de autenticação para aplicações. Ele nos ajuda a identificar quem é o usuário que está acessando nossa aplicação e gerar credenciais de acesso que são atualizadas automaticamente.&lt;/p&gt;

&lt;p&gt;Os Identity pools (ou grupos de identidade) são diretórios de identidades que podem ser usados para obter credenciais para acessar outros serviços da AWS através do nosso front-end. Para criá-lo, siga os passos abaixo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Na sua conta Free Tier, navegue até o &lt;a href="https://us-west-2.console.aws.amazon.com/cognito/v2/home?region=us-west-2&amp;amp;trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Cognito&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Selecione "Grupos de identidades" no menu esquerdo e em seguida "Criar grupo de identidades" no botão laranja à direita&lt;/li&gt;
&lt;li&gt;Na página de criação, selecione "Acesso de convidado". Isso permitirá que nosso código front-end acesse os recursos que queremos sem precisar de um login. Clique em "Próxima" para continuar&lt;/li&gt;
&lt;li&gt;Em seguida, vamos criar um perfil do IAM que usaremos para declarar as permissões. Selecione "Criar um novo perfil do IAM" e dê um nome a ele. Chamei o meu de "jsWebClientRole". Clique em "Próxima" para continuar&lt;/li&gt;
&lt;li&gt;Dê um nome ao grupo de identidades. Chamei o meu de "jsWebClientIdentity". Clique em "Próxima" para continuar&lt;/li&gt;
&lt;li&gt;Revise os detalhes do grupo de identidade que estamos criando e selecione "Criar grupo de identidades" para concluir.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;De volta na página dos Grupos de identidade do Amazon Cognito, você verá seu grupo de identidade criado. Salve o ID dele pois será usado logo mais para autenticação no código.&lt;/p&gt;

&lt;p&gt;Por último, precisamos ligar a política de acesso que criamos na seção anterior ao grupo de identidade:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navegue até o &lt;a href="https://us-west-2.console.aws.amazon.com/iam/home?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;console de IAM&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;No menu esquerdo, selecione "Funções" &lt;/li&gt;
&lt;li&gt;Busque pelo perfil que criamos junto ao Grupo de identidade. O meu é o "jsWebClientRole"&lt;/li&gt;
&lt;li&gt;Na aba de "Permissões", selecione "Adicionar permissões" e "Anexar políticas"&lt;/li&gt;
&lt;li&gt;Busque pela política de acesso ao S3 que criamos anteriormente e clique em "Adicionar permissão"&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Configurando CORS
&lt;/h2&gt;

&lt;p&gt;Um conceito clássico que vemos quando integramos aplicações, como integração entre front e back-end, é CORS. CORS significa Cross-Origin Resource Sharing, ou compartilhamento de recursos entre origens, e é um mecanismo para compartilhar conteúdo entre diferentes domínios de forma segura. Com ele, declaramos o que pode ser compartilhado e quais domínios podem enviar conteúdo. Precisamos configurar CORS para o bucket de input e de output.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;No console da AWS, navegue até a &lt;a href="https://us-west-2.console.aws.amazon.com/s3?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;página do S3&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Selecione o nome do bucket de input que criamos no último tutorial quando construímos o back-end&lt;/li&gt;
&lt;li&gt;Clique em "Permissões" e desça até o final da página onde encontrará "Compartilhamento de recursos de origem cruzada (CORS)"&lt;/li&gt;
&lt;li&gt;Clique em editar e cole o conteúdo abaixo:
&lt;/li&gt;
&lt;/ol&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="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"AllowedHeaders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"AllowedMethods"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"PUT"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"AllowedOrigins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:3000"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ExposeHeaders"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"ETag"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&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;blockquote&gt;
&lt;p&gt;⚠️ Note que adicionamos especificamente o localhost na porta 3000 em "AllowedOrigins" o que significa que o bucket aceitará receber recursos apenas desse domínio. A melhor prática de segurança é sempre restringir acesso para o mínimo necessário. Para um site que estivesse deployado na internet, adicionaríamos o domínio específico da aplicação que faz o envio.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Repita os mesmos passos para habilitar CORS no bucket de output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conectando tudo: chamando o SDK da AWS
&lt;/h2&gt;

&lt;p&gt;Agora que temos as permissões configuradas na conta AWS, vamos fazer a conexão com o S3 no código.&lt;/p&gt;

&lt;p&gt;No começo do arquivo App.js do repositório clonado, você encontrará o seguinte trecho:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-west-2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IDENTITY_POOL_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clienteS3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fromCognitoIdentityPool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;clientConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="na"&gt;identityPoolId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IDENTITY_POOL_ID&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;O IdentityPoolId usado para criar o clienteS3 será o ID do Grupo de Identidades que criamos com Amazon Cognito. Preencha esse valor na constante &lt;code&gt;IDENTITY_POOL_ID&lt;/code&gt;. Note que a constante &lt;code&gt;REGION&lt;/code&gt;, que indica a região, está declarada como &lt;code&gt;us-west-2&lt;/code&gt;. Caso seus recursos estejam em outra região da AWS, mude essa constante para a região correspondente.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Essa é a forma recomendada pela AWS para obter credenciais para o navegador. &lt;strong&gt;Muito cuidado com expor suas credenciais abertamente, jamais publique elas na internet!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Por fim, preencha as constantes que representam os buckets de input e output com os nomes dos seus buckets:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BUCKET_ENTRADA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BUCKET_SAIDA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto! Se seu back-end também estiver configurado, você terá um sistema completo incluindo front e back-end que utiliza o SDK da AWS para comunicação com os serviços em nuvem. Você pode usar &lt;a href="https://github.com/gi-armani/CSV-JSON-Converter-sample-for-aws-SDK/blob/main/exemplo-produtos.csv" rel="noopener noreferrer"&gt;esse csv de exemplo&lt;/a&gt; para testar a aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Agora você já sabe como construir uma aplicação front-end que se comunica diretamente com serviços da AWS. Nesse tutorial, você aprendeu a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instalar e usar o AWS SDK para JavaScript para interagir com o S3&lt;/li&gt;
&lt;li&gt;Configurar permissões no IAM para que sua aplicação acesse serviços da AWS de forma segura&lt;/li&gt;
&lt;li&gt;Configurar CORS para permitir a comunicação entre seu front-end e a nuvem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reproduza esse tutorial na sua máquina e dê seu próprio estilo ao design da página. Experimente trocar cores, fontes e layout, deixe com a sua carinha. Com o front-end e o back-end que construímos no artigo anterior, você tem uma aplicação serverless completa funcionando na AWS!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>development</category>
      <category>programming</category>
    </item>
    <item>
      <title>Seus primeiros passos com computação em nuvem</title>
      <dc:creator>Giovana Armani</dc:creator>
      <pubDate>Fri, 13 Mar 2026 21:12:21 +0000</pubDate>
      <link>https://forem.com/aws/seus-primeiros-passos-com-computacao-em-nuvem-30fd</link>
      <guid>https://forem.com/aws/seus-primeiros-passos-com-computacao-em-nuvem-30fd</guid>
      <description>&lt;p&gt;Não tem jeito melhor de aprender sobre computação em nuvem do que colocando a mão na massa. Venha entender do que se trata essa tecnlogia e criar uma página pessoal na nuvem (mais fácil do que você imagina)!&lt;/p&gt;

&lt;h2&gt;
  
  
  O que faz uma aplicação?
&lt;/h2&gt;

&lt;p&gt;Uma aplicação é composta por diversas partes diferentes como vemos no diagrama abaixo:&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.amazonaws.com%2Fuploads%2Farticles%2F8guyurf2x463inn66qtk.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.amazonaws.com%2Fuploads%2Farticles%2F8guyurf2x463inn66qtk.png" alt="Diagrama exemplo de uma aplicação" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autenticação/autorização: a forma que uma aplicação descobre &lt;em&gt;quem&lt;/em&gt; está tentando acessar e &lt;em&gt;o que&lt;/em&gt; ela tem permissão de fazer&lt;/li&gt;
&lt;li&gt;Front-end: elementos visuais da aplicação, como as telas de aplicativos&lt;/li&gt;
&lt;li&gt;Back-end: onde acontece o processamento dos dados que são mostrados&lt;/li&gt;
&lt;li&gt;Banco de dados: onde são guardadas informações como texto, números, datas, etc&lt;/li&gt;
&lt;li&gt;Armazenamento de arquivos: para guardar arquivos como imagens, audios, pdfs, etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Existem ainda vários outros componentes como serviços de rede, segurança, monitoramento, mensagerias, entre outros.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é computação em nuvem?
&lt;/h2&gt;

&lt;p&gt;Antigamente, as empresas donas de aplicações precisavam construir do zero cada uma dessas e das várias outras partes que compõe um sistema. Para rodar as aplicações, era preciso cuidar dos próprios &lt;strong&gt;servidores&lt;/strong&gt;, os super computadores que executam progamas e armazenam e transferem dados, como os mostrados abaixo. Isso acabava sendo caro porque os servidores precisam do seu próprio lugar para ser mantidos, os famosos &lt;strong&gt;data centers&lt;/strong&gt;. Além disso, manter um servidor exige bastante trabalho e uma equipe tecnica especializada para mantê-los atualizados e seguros. Isso sem contar o espaço físico, eletricidade e refrigeração que essas máquinas precisam... ufa, coisa demais!&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.amazonaws.com%2Fuploads%2Farticles%2Fxudhs5yh7wjqof5hotdt.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.amazonaws.com%2Fuploads%2Farticles%2Fxudhs5yh7wjqof5hotdt.jpg" alt="Servidores enfileirados" width="800" height="599"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A computação em nuvem veio para revolucionar isso porque agora não é mais preciso ter seus próprios servidores e data centers. Podemos "pegar emprestado" das empresas &lt;strong&gt;provedoras de nuvem&lt;/strong&gt;, como a AWS. Não só isso facilita para empresas crescerem, mas oferece aos devs a possibilidade de construir sistemas dos mais malucos sem sair do seu computador. &lt;/p&gt;

&lt;p&gt;É comum dizermos que a computação em nuvem é &lt;em&gt;a entregra sob demanda de recursos de TI através da internet&lt;/em&gt;, mas o que significa isso, afinal? &lt;/p&gt;

&lt;p&gt;Os "recursos de TI" são aquelas várias partes que formam um sistema que podemos encontar na nuvem como blocos de construção de aplicações. Já quando dizemos "entrega sob demanda", significa que podemos usar os serviços em nuvem apenas enquanto precisamos e liberá-los quando não forem mais necessários.&lt;/p&gt;

&lt;p&gt;Dessa forma, temos mais agilidade e redução de custo porque pagamos pelos recursos computacionais só enquanto estão sendo usados na nossa aplicação. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conta Free Tier da AWS
&lt;/h2&gt;

&lt;p&gt;Falando em pagamento, um grande medo dos desenvolvedores quando estão aprendendo sobre computação em nuvem e querem experimentar é não se atentar aos preços e acabar recebendo uma fatura surpresa...&lt;/p&gt;

&lt;p&gt;Pensando nisso, a AWS lançou a conta Free Tier. Ao criá-la, você ganha 100 créditos na conta e pode ganhar até 100 créditos adicionais ao explorar os diferentes serviços da AWS e não será cobrado a não ser que expliticamente escolha trocar de plano - sem cobranças supresa! Se quiser saber mais sobre como criar sua conta e as melhores configurações de segurança veja &lt;a href="https://builder.aws.com/content/2lYwQJ47Sq8C76VkFUDisXB7VnN/secure-foundation-setting-up-your-aws-free-tier-account" rel="noopener noreferrer"&gt;esse artigo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Construindo sua primeira aplicação em nuvem
&lt;/h2&gt;

&lt;p&gt;Para começar a brincar com a nuvem, vamos construir uma aplicação simples, mas fundamental para qualquer desenvolvedor: um portifolio pessoal online! Construiremos um site estático e publicaremos ele na internet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando a aplicação localmente
&lt;/h3&gt;

&lt;p&gt;Para mostrar que você pode começar na nuvem independente do seu nível de conhecimento e momento de carreira, vou construir uma aplicação bem simples com as tecnologias que eu usava quando comecei a aprender sobre desenvolvimento: html e css. &lt;/p&gt;

&lt;p&gt;Html é a linguagem de script que permite criar a estrutura dos sites com elementos como botões, inputs, textos. Já com CSS, configurmos o estilo da página.&lt;/p&gt;

&lt;p&gt;Deixei abaixo um print da minha versão de página pessoal (super simples, vou incrementar com o tempo) e &lt;a href="//github.com/gi-armani/SitePessoal"&gt;nesse repositório&lt;/a&gt; deixei o código fonte para servir de base ou inspiração para seus projetos.&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.amazonaws.com%2Fuploads%2Farticles%2F4sqzq0d7ds6divhf7p9x.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.amazonaws.com%2Fuploads%2Farticles%2F4sqzq0d7ds6divhf7p9x.png" alt="Print da minha página pessoal" width="788" height="910"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Caso você queira começar rápido, é possível fazer um esboço do site em um editor de imagem e enviar para a sua IA de preferencia pendindo para ela criar o código base, eu recomendo o Kiro 😉.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployando a aplicação para a nuvem
&lt;/h3&gt;

&lt;p&gt;Agora para subir o site na internet, vamos usar AWS Amplify. Esse é o serviço da AWS que oferece uma plataforma de desenvolvimento para criação de páginas web e móveis de forma fácil e rápida. Para subir sua aplicação, siga os passos a seguir: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Em sua conta Free Tier da AWS, navegue até o AWS Amplify &lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;Implemente uma aplicação&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Selecione &lt;strong&gt;Implantar sem git&lt;/strong&gt; ou escolha a fonte de código da sua preferência&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;Próximo&lt;/strong&gt; e dê um nome para sua aplicação&lt;/li&gt;
&lt;li&gt;Compacte seus arquivos e adicione-os no console. Compacte os arquivos em si, não o diretório em que eles estão&lt;/li&gt;
&lt;li&gt;Nomeie o zip como index.zip&lt;/li&gt;
&lt;li&gt;Clique em &lt;strong&gt;Salvar e implantar&lt;/strong&gt;. A página vai carregar por alguns segundos e te direcionar para a página da aplicação. Em &lt;strong&gt;domínio&lt;/strong&gt; você encontra o link para sua aplicação. Você pode até abrir no celular - sua aplicação está no ar e funcionando!&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fgmdhhq3qievvkipu0y89.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.amazonaws.com%2Fuploads%2Farticles%2Fgmdhhq3qievvkipu0y89.png" alt="Console AWS Amplify" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Agora que você já sabe como deployar uma aplicação na nuvem, deixo para você aproveitar o free tier para explorar diferentes integrações e serviços. A melhor forma de aprender é experimentando!&lt;/p&gt;

&lt;p&gt;Quer ir além do front-end e trabalhar com back-end? Tenho outro artigo sobre como &lt;a href="https://dev.to/aws/seu-primeiro-sistema-serverless-com-aws-lambda-7ai"&gt;construir seu primeiro sistema serverless com AWS Lambda&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Se tiver dúvidas ou quiser compartilhar feedback, fique à vontade para me procurar!&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>cloudcomputing</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>SDK: as ferramentas para seu código se conectar com o mundo</title>
      <dc:creator>Giovana Armani</dc:creator>
      <pubDate>Thu, 05 Mar 2026 21:58:25 +0000</pubDate>
      <link>https://forem.com/aws/sdk-as-ferramentas-para-seu-codigo-se-conectar-com-o-mundo-5d0e</link>
      <guid>https://forem.com/aws/sdk-as-ferramentas-para-seu-codigo-se-conectar-com-o-mundo-5d0e</guid>
      <description>&lt;p&gt;Se você já tentou integrar sua aplicação com serviços externos como serviços de nuvem, aplicativos de localização, autenticação ou pagamento, provavelmente já usou um SDK sem nem perceber. Mas afinal, o que é um SDK e por que ele é importante para nós desenvolvedores?&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é SDK?
&lt;/h2&gt;

&lt;p&gt;SDK significa &lt;strong&gt;Software Development Kit&lt;/strong&gt; (em português Kit de Desenvolvimento de Software). Gosto de pensar nele como uma caixa de ferramentas para construir aplicações sobre uma plataforma, sistema operacional ou linguagem de programaçã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.amazonaws.com%2Fuploads%2Farticles%2F28u7piz6mqhbb51xsady.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.amazonaws.com%2Fuploads%2Farticles%2F28u7piz6mqhbb51xsady.png" alt="Caixa de ferramentas com ferramentas dentro com tags de APIs, bibliotecas, exemplos de código, documentação" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um SDK geralmente inclui:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bibliotecas de código&lt;/strong&gt; prontas para usar&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APIs&lt;/strong&gt; para comunicação com serviços (leia mais sobre o que é uma API &lt;a href="https://aws-amazon-com.translate.goog/what-is/api/?_x_tr_sl=en&amp;amp;_x_tr_tl=pt&amp;amp;_x_tr_hl=pt&amp;amp;_x_tr_pto=tc&amp;amp;trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;nesse link&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentação&lt;/strong&gt; detalhada&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplos de código&lt;/strong&gt; práticos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ferramentas de desenvolvimento&lt;/strong&gt; (debuggers, compiladores, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Por que SDKs existem?
&lt;/h2&gt;

&lt;p&gt;SDKs existem para &lt;strong&gt;acelerar o desenvolvimento&lt;/strong&gt; e &lt;strong&gt;reduzir a complexidade&lt;/strong&gt;. Eles reunem toda a lógica complicada de integração, permitindo que você foque na funcionalidade da sua aplicação.&lt;/p&gt;

&lt;p&gt;Vamos imaginar, por exemplo, que você está construindo um sistema de vendas e quer adicionar a possibilidade de pagamentos. Ao invés de programar essa funcionalidade do zero e ainda fazer as integrações com sua aplicação, você pode usar um SDK! &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.amazonaws.com%2Fuploads%2Farticles%2Fw92ildftf4lsqvd6651e.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.amazonaws.com%2Fuploads%2Farticles%2Fw92ildftf4lsqvd6651e.png" alt="Fluxo de uso de um SDK" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usando em código, um o uso de um SDK de pagamentos, como o do Paypal, se pareceria com algo assim:&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="c1"&gt;// Importar o SDK do PayPal&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;paypal&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@paypal/checkout-server-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Configurar o SDK com suas credenciais&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;idCliente&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;seu-id-cliente&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;segredoCliente&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;seu-segredo-cliente&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ambiente&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;paypal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SandboxEnvironment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idCliente&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;segredoCliente&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cliente&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;paypal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PayPalHttpClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ambiente&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Criar um pedido de pagamento&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;criarPagamento&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requisicao&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;paypal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OrdersCreateRequest&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;requisicao&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestBody&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CAPTURE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;purchase_units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;currency_code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;29.99&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Assinatura Premium&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="c1"&gt;// O SDK cuida da requisição HTTP, autenticação e resposta&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resposta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cliente&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requisicao&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pagamento criado:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resposta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resposta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;criarPagamento&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sem um SDK, você precisaria manualmente lidar com requisições HTTP, gerenciar autenticação, tratar erros e muito mais. O SDK faz tudo isso por você!&lt;/p&gt;

&lt;h2&gt;
  
  
  Qual é a diferença entre SDK, API e Bibliotecas?
&lt;/h2&gt;

&lt;p&gt;Começando com as definições, já vimos que um SDK é kit de desenvolvimento com várias ferramentas. Uma API é um contrato de comunicação entre programas que especifica como informações vão ser passadas entre eles. Por último, uma biblioteca é um conjunto de funções que podem ser reutilizadas por vários programas.&lt;/p&gt;

&lt;p&gt;Passando para um exemplo do mundo real, imagine que o mundo dos códigos seja um restaurante. Bibliotecas são os livros de receita que ensinam a fazer pratos específicos. As APIs são o cardápio que mostram o que um cliente pode pedir e como. Já o SDK é a cozinha completa com várias ferramentas para preparar o que você quiser.&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.amazonaws.com%2Fuploads%2Farticles%2Fa1arm9mickjlfnu0jfc8.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.amazonaws.com%2Fuploads%2Farticles%2Fa1arm9mickjlfnu0jfc8.png" alt="Analogia da cozinha ilustrada" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na imagem acima, as bibliotecas estão dentro das APIs que estão dentro dos SDKs, mas lembre-se que elas podem existir independentemente tambem.&lt;/p&gt;

&lt;p&gt;Resumindo:&lt;/p&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;SDK&lt;/th&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Biblioteca&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;O que é&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kit completo de ferramentas para desenvolvimento&lt;/td&gt;
&lt;td&gt;Contrato de comunicação entre programas&lt;/td&gt;
&lt;td&gt;Coleção de funções reutilizáveis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Propósito&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Facilitar desenvolvimento para uma plataforma&lt;/td&gt;
&lt;td&gt;Permitir integração entre sistemas&lt;/td&gt;
&lt;td&gt;Resolver problemas específicos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Exemplos&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SDK do Google para Android, Stripe SDK para pagamentos, SDK do Facebook, SDK do Arduino para IOT&lt;/td&gt;
&lt;td&gt;REST API do Twitter, Web API do Spotify, API do Github, API da NASA&lt;/td&gt;
&lt;td&gt;Pandas (manipulação de dados com python), Lodash (utilitários do javascript), Gson (manipulação de json em java), NLog (registros de log para C# e .NET)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Aspectos essenciais de um SDK
&lt;/h2&gt;

&lt;p&gt;Ao escolher um SDK para usar no seu projeto, é importante considerar:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Licença&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;É open source ou proprietário? SDKs open source são livres para ser usados por todos (e você pode até colaborar com a construção deles!), já os proprietários, é possível que você precise de permissão para usar&lt;/li&gt;
&lt;li&gt;Quais são as restrições de uso?&lt;/li&gt;
&lt;li&gt;Há custos associados?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Documentação&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A documentação é clara e completa?&lt;/li&gt;
&lt;li&gt;Existem exemplos práticos?&lt;/li&gt;
&lt;li&gt;Há guias de início rápido?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Compatibilidade&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Funciona com a linguagem que você está usando?&lt;/li&gt;
&lt;li&gt;É compatível com as versões que você tem dessa linguagem?&lt;/li&gt;
&lt;li&gt;Suporta as plataformas que você precisa (web, mobile, server)?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Suporte&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Há uma comunidade ativa?&lt;/li&gt;
&lt;li&gt;O SDK é mantido regularmente?&lt;/li&gt;
&lt;li&gt;Existe suporte oficial?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Segurança&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Como as credenciais são gerenciadas?&lt;/li&gt;
&lt;li&gt;Há atualizações de segurança regulares?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Agora você já sabe o que é um SDK e como ele difere de APIs e bibliotecas! SDKs são ferramentas poderosas que economizam tempo e reduzem a complexidade ao integrar sua aplicação com plataformas externas.&lt;/p&gt;

&lt;p&gt;No meu último artigo, usei o SDK da AWS para construir uma aplicação com função Lambda do zero (veja no &lt;a href="https://dev.to/aws/seu-primeiro-sistema-serverless-com-aws-lambda-7ai"&gt;artigo&lt;/a&gt; o passo a passo) e nem contei pra vocês! Na próxima semana, vamos explorar ainda mais o SDK da AWS para javascript!&lt;/p&gt;

</description>
      <category>development</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Seu primeiro sistema serverless com AWS Lambda</title>
      <dc:creator>Giovana Armani</dc:creator>
      <pubDate>Thu, 26 Feb 2026 22:29:58 +0000</pubDate>
      <link>https://forem.com/aws/seu-primeiro-sistema-serverless-com-aws-lambda-7ai</link>
      <guid>https://forem.com/aws/seu-primeiro-sistema-serverless-com-aws-lambda-7ai</guid>
      <description>&lt;p&gt;A ideia de subir código na nuvem pode parecer muito complexa para quem nunca fez isso antes. E se chover? Ai ferrou minha aplicação...&lt;br&gt;
Brincadeirinhas à parte, juro que é mais tranquilo do que parece. Nesse artigo vamos construir uma aplicação na nuvem do zero usando &lt;a href="https://docs.aws.amazon.com/pt_br/lambda/?icmpid=docs_homepage_featuredsvcs&amp;amp;trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt;!&lt;/p&gt;


&lt;h2&gt;
  
  
  O que é AWS Lambda?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/pt_br/lambda/?icmpid=docs_homepage_featuredsvcs&amp;amp;trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; é um serviço da AWS que permite você criar sistemas serverless. Isso significa que você não precisa configurar os servidores do seu sistema, a nuvem faz isso pra você e você fica livre pra focar no código! Para saber mais sobre serverless e suas vantagens e desvantagens, veja esse artigo: &lt;a href="https://dev.to/giarmani/a-verdade-oculta-por-tras-do-serverless-55f7"&gt;A verdade oculta por trás do Serverless&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uma &lt;strong&gt;função Lambda&lt;/strong&gt; é uma unidade de código que fica na nuvem esperando ser chamada para executar alguma tarefa. Chamamos de &lt;strong&gt;evento&lt;/strong&gt; o acontecimento que aciona a função. Em sistemas gerais, esse evento pode ser uma notificação, uma atualização no banco de dados, um usuário apertando um botão, entre outros. Após ser acionada, uma função Lambda pode executar várias tarefas, inclusive chamar outros serviços como um banco de dados.&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.amazonaws.com%2Fuploads%2Farticles%2Fynipohkevt9e5gx9xgdw.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.amazonaws.com%2Fuploads%2Farticles%2Fynipohkevt9e5gx9xgdw.png" alt="Diagrama de funcionamento lambda" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Por onde começar?
&lt;/h2&gt;

&lt;p&gt;Tudo que veremos nesse post pode ser replicada em uma &lt;a href="https://aws.amazon.com/free/?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;conta free tier&lt;/a&gt; da AWS! Ela permite que você comece a explorar vários serviços da AWS gratuitamente e apenas será cobrado caso escolha trocar de plano. Aprenda mais sobre o free tier e como setar sua conta &lt;a href="https://builder.aws.com/content/2lYwQJ47Sq8C76VkFUDisXB7VnN/secure-foundation-setting-up-your-aws-free-tier-account?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;nesse post&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Nossa aplicação de exemplo
&lt;/h3&gt;

&lt;p&gt;Para demonstrar como subir e rodar código na nuvem, vamos construir uma aplicação que transforma arquivos CSV (ou planilhas de Excel) em JSON. Sei que existem sites que já fazem isso gratuitamente, mas às vezes precisamos converter arquivos privados e sensíveis que talvez a gente não queira subir em um sistema de outros. Em momentos como esse, é muito bom ser dev e conseguir construir sua própria solução rapidinho!&lt;/p&gt;

&lt;p&gt;O diagrama abaixo demonstra o funcionamento do nosso programa. Vamos subir o arquivo que queremos converter em um bucket do &lt;a href="https://docs.aws.amazon.com/pt_br/AmazonS3/latest/userguide/Welcome.html?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon S3&lt;/a&gt; (Amazon Simple Storage Service). Ele é um serviço de armazenamento de arquivos oferecido pela AWS. A ação de colocar o arquivo no bucket vai acionar nossa função lambda. Ela vai buscar o arquivo no bucket, converter para JSON e colocar o arquivo convertido em outro bucket de output.&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.amazonaws.com%2Fuploads%2Farticles%2F96ermmpxke68u3ylmo1p.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.amazonaws.com%2Fuploads%2Farticles%2F96ermmpxke68u3ylmo1p.png" alt="Arquitetura da aplicação" width="561" height="211"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Construindo a aplicação
&lt;/h2&gt;

&lt;p&gt;Listarei a seguir os passos que segui para construir a aplicação. Siga os passos para construir comigo ou acompanhe o processo pelo video no final. &lt;/p&gt;

&lt;p&gt;Você sabia que pode configurar as páginas da conta AWS para ficar em português caso não esteja automaticamente? Assim que entrar na sua conta, selecione o ícone de engrenagem à direita da tela e no dropdown embaixo de "Language", selecione "Portugês"!&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.amazonaws.com%2Fuploads%2Farticles%2F7yggzt878e76o9s6ua25.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.amazonaws.com%2Fuploads%2Farticles%2F7yggzt878e76o9s6ua25.png" alt="Console AWS em português" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Criando a função inicial
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Na conta free tier da AWS, naveguei até a &lt;a href="https://console.aws.amazon.com/lambda/home" rel="noopener noreferrer"&gt;página do Lambda&lt;/a&gt; através da caixa de busca&lt;/li&gt;
&lt;li&gt;Cliquei em "Criar função"&lt;/li&gt;
&lt;li&gt;Chamei minha função de &lt;code&gt;csvToJsonConverter&lt;/code&gt; e selecionei nodejs24.x como linguagem. Outras configurações mantive como default&lt;/li&gt;
&lt;li&gt;Cliquei em "Criar função" no canto inferior direito da página para criar e ser direcionada para a página da função
&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.amazonaws.com%2Fuploads%2Farticles%2Fmdadjxudnb6g5f0wl6uw.png" alt="Console AWS demonstrando editor de código na página do Lambda" width="800" height="372"&gt;
&lt;/li&gt;
&lt;li&gt;Na seção de Configurações de tempo de execução, me certifiquei que o manipulador era &lt;strong&gt;index.handler&lt;/strong&gt;, para indicar o ponto de entrada da aplicação&lt;/li&gt;
&lt;li&gt;Na página da função Lambda, na aba de código, existe um editor de texto, como demonstrado na imagem acima, que pode ser usado para escrever o código da função. Essa funcionalidade está disponível para códigos em Node.js, Python e Ruby. Nele, já existia um arquivo chamado index.mjs que serve como porta de entrada do programa. Em funções Lambda, essa porta de entrada é chamada de &lt;em&gt;handler&lt;/em&gt; e no console da AWS em português é traduzido como "manipulador". Adicionei apenas um log no arquivo para validar minha estrutura inicial:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Handler chamado!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Minha primeira função!&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&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;Parabéns! Você escreveu seu primeiro código na Lamba! Agora clique&lt;br&gt;
no botão "Deploy" para subir o código para a função lambda!&lt;/p&gt;

&lt;p&gt;Após criar essa estrutura inicial é possível testar a chamada para a função na aba de "Testar" e ver nos logs da execução se nosso código está sendo chamado como esperado. Para isso, mantive todas as configrações da aba de teste como estavam e apenas cliquei em "Testar".&lt;/p&gt;
&lt;h3&gt;
  
  
  Criando os buckets S3
&lt;/h3&gt;

&lt;p&gt;Os buckets vão servir para armazenar nossos arquivos de entrada e de saída. Vamos criá-los!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Naveguei até a &lt;a href="https://console.aws.amazon.com/s3" rel="noopener noreferrer"&gt;página do S3&lt;/a&gt; pelo console da AWS
&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.amazonaws.com%2Fuploads%2Farticles%2F1fqqjchp6aobqslea08h.png" alt="Console AWS na página de configuração do bucket S3" width="800" height="384"&gt;
&lt;/li&gt;
&lt;li&gt;Cliquei em "Criar bucket" e chamei o bucket de &lt;code&gt;gio-csv-converter-input&lt;/code&gt; e mantive outras configurações default &lt;em&gt;(lembre-se de **sempre&lt;/em&gt;* bloquear todo o acesso público)*. Os nomes de buckets no S3 são únicos globalmente, então você não conseguirá usar o mesmo nome de bucket que o meu. Sugiro usar &lt;code&gt;&amp;lt;seu-nome&amp;gt;-csv-converter-input&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Cliquei em "Criar bucket" no final da tela de configurações para criar&lt;/li&gt;
&lt;li&gt;Criei também outro bucket chamado &lt;code&gt;gio-csv-converter-output&lt;/code&gt; que servirá para guardar os arquivos convertidos. Novamente, você precisará de um nome de bucket diferente. Sugiro &lt;code&gt;&amp;lt;seu-nome&amp;gt;-csv-converter-output&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Novamente, cliquei em "Criar bucket" no final da tela&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Adicionando a conexão com o S3
&lt;/h3&gt;

&lt;p&gt;Como vimos anteriormente, quando colocarmos um arquivo no bucket do S3, nossa função lambda vai ser acionada. Agora temos que avisar a AWS que vai ser assim&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;De volta na &lt;a href="https://console.aws.amazon.com/lambda/home" rel="noopener noreferrer"&gt;página da função lambda&lt;/a&gt;, cliquei em "Adicionar gatilho"
&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.amazonaws.com%2Fuploads%2Farticles%2Fb71wpm2k8lpe8qragj2c.png" alt="Console AWS na página de criação de gatilho para função Lambda" width="800" height="294"&gt;
&lt;/li&gt;
&lt;li&gt;No dropdown de seleção procurei por "S3" e selecionei o serviço&lt;/li&gt;
&lt;li&gt;Cliquei no campo de "bucket" e selecionei meu bucket de input&lt;/li&gt;
&lt;li&gt;No campo de "Event types" selecionei "All object create events" que significa que será acionando smepre que um novo arquivo for adicionado no bucket&lt;/li&gt;
&lt;li&gt;Mantive os campos de "Prefix" e "Sufix" vazios&lt;/li&gt;
&lt;li&gt;Cliquei na caixa de seleção no campo de "Recursive invocation". Infelizmente a mensagem dela ainda não foi traduzida para o português, mas a tradução seria: Reconheço que usar o mesmo bucket S3 para entrada e saída não é recomendado e que essa configuração pode causar invocações recursivas, aumento no uso do Lambda e aumento nos custos. É por esse motivo que criamos buckets separados para o input e output. Se colocássemos o arquivo final do mesmo bucket de input, a lambda seria acionada novamente e entraríamos em um loop infinito (que eventualmente ia custar uma fortuna!)&lt;/li&gt;
&lt;li&gt;Por fim, cliquei em "Adicionar" para criar o gatilho&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ao adicionarmos o S3 como gatilho para a função Lambda, a AWS vai automaticamente configurar as permissões para que o S3 possa acioná-la.&lt;/p&gt;

&lt;p&gt;É possível ainda testar essa conexão pelo console navegando até o S3 e subindo um arquivo no bucket. Podemos ver os logs da nossa aplicação através do &lt;a href="https://aws.amazon.com/pt/cloudwatch/?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon CloudWatch&lt;/a&gt;, o serviço de monitoramento de aplicações da AWS, seguindo os passos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Usando a caixa de pesquisa do console da AWS, navegue para a &lt;a href="https://console.aws.amazon.com/cloudwatch/home" rel="noopener noreferrer"&gt;página do CloudWatch&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;No menu à esquerda, clique em Logs &amp;gt; Gerenciamento de logs&lt;/li&gt;
&lt;li&gt;Clique no nome da sua função Lambda que aparecerá na lista de Log groups&lt;/li&gt;
&lt;li&gt;Procure pelo arquivo de log correspondente ao horário em que você executou a função&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fdnjw3vs99z69lvn1opbb.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.amazonaws.com%2Fuploads%2Farticles%2Fdnjw3vs99z69lvn1opbb.png" alt="Console AWS mostrando logs no Cloudwatch" width="800" height="259"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementação de funcionalidade e permissões
&lt;/h3&gt;

&lt;p&gt;Usei a biblioteca &lt;code&gt;@aws-sdk/client-s3&lt;/code&gt; (&lt;a href="https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/" rel="noopener noreferrer"&gt;clique aqui para a documentação&lt;/a&gt;) para conexão com os buckets S3 para acessar os arquivos. Escrevendo o código diretamente pelo console do Lambda, pude simplemente importar o que precisava sem instalar a biblioteca porque as funções Lambda já tem acesso ao &lt;a href="https://github.com/aws/aws-sdk-js" rel="noopener noreferrer"&gt;SDK da AWS&lt;/a&gt; implicitamente. Para converter o conteúdo CSV para JSON, usei simples manipulação de string do javascript. Veja o código completo abaixo ou &lt;a href="https://github.com/gi-armani/CSVToJSONConverter" rel="noopener noreferrer"&gt;nesse repositório&lt;/a&gt;.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;GetObjectCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PutObjectCommand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-sdk/client-s3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s3Client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OUTPUT_BUCKET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gio-csv-converter-output&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;abacaxi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`event: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sourceBucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sourceKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;destinationKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sourceKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.csv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csvContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getCSVFromS3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sourceKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jsonData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;csvToJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csvContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;uploadJsonToS3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destinationKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jsonData&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="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CSV converted to JSON successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceBucket&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;sourceKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;OUTPUT_BUCKET&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;destinationKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error processing file:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCSVFromS3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sourceKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GetObjectCommand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sourceBucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sourceKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3Client&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="nx"&gt;getCommand&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;csv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transformToString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`String do csv puxado do S3: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;csvToJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csvContent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;csvContent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Lines: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Headers: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;obj&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="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;uploadJsonToS3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destinationKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;putCommand&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PutObjectCommand&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OUTPUT_BUCKET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;destinationKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;ContentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;s3Client&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="nx"&gt;putCommand&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;Caso copie o código acima no editor de texto da função lambda para testar, não se esqueça de clicar em "Deploy"!&lt;/p&gt;

&lt;p&gt;Uma coisa importante de configurar também são as permissões para a função Lambda conseguir acessar os buckets. Se quiser entender mais sobre como funciona o IAM e os diferentes tipos de permissão veja &lt;a href="https://builder.aws.com/content/35z2TS8V8AIpEqHm1bdM7LLa2hz/desmistificando-permissoes-na-aws?trk=4c2f66ff-5d75-4a07-aa36-eb6219a429db&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;esse artigo&lt;/a&gt;, mas em linhas gerais, segui esses passos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Na página da minha função Lambda, acessei a aba de "Configuração"&lt;/li&gt;
&lt;li&gt;No menu esquerdo, selecionei "Permissões"&lt;/li&gt;
&lt;li&gt;Cliquei no link embaixo de "Noma da função" que me direcionou para a &lt;a href="https://console.aws.amazon.com/iam/home" rel="noopener noreferrer"&gt;página do IAM&lt;/a&gt; (AWS Identity and Access Management). Esse é o serviço que permite gerenciar permissões dentro da sua conta AWS
&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.amazonaws.com%2Fuploads%2Farticles%2F1gb89x141n1s62rh36l3.png" alt="Console AWS demonstrando como achar role da função" width="800" height="307"&gt;
&lt;/li&gt;
&lt;li&gt;A página do IAM foi aberta diretamente na role da função Lambda que gerencia o que ela pode fazer em outros serviços. Cliquei em "Adicionar permissões" &amp;gt; "Criar política em linha"&lt;/li&gt;
&lt;li&gt;Fui direcionada para a página do Policy Editor onde selecionei formato JSON e adicionei a permissão abaixo. Cliquei em "Próximo" no canto inferior da página e chamei a política de "AcessoAoS3" e cliquei em "Criar política" para terminar a criação
&lt;/li&gt;
&lt;/ol&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="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GetObjectPermission"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::&amp;lt;nome-do-bucket-de-input&amp;gt;/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PutObjectPermission"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::&amp;lt;nome-do-bucket-de-output&amp;gt;/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&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;Podemos ver que essa permissão contém dois objetos dentro do array de "Statement". Cada objeto desses concede um acesso diferente. O primeiro permite (sinalizado pelo &lt;code&gt;"Effect": "Allow"&lt;/code&gt;) que nossa função faça a ação de "GetObject" sobre o bucket de input. Ou seja, a função vai poder pegar os arquivos que colocarmos no bucket de input para fazer a conversão. Já o segundo, permite que a função faça a ação de "PutObject" no bucket de output, ou seja, coloque os arquivos convertidos no bucket para podermos baixar.&lt;/p&gt;

&lt;p&gt;⚠️ Não se esqueça de trocar os nomes dos buckets na permissão acima pelo nome dos seus buckets!&lt;/p&gt;

&lt;h3&gt;
  
  
  Testando tudo junto!
&lt;/h3&gt;

&lt;p&gt;Está pronto! Agora podemos testar a aplicação final!&lt;/p&gt;

&lt;p&gt;Usei &lt;a href="//./exemplo-produtos.csv"&gt;esse csv de exemplo&lt;/a&gt; e coloque ele no meu bucket de input do S3. É possível ver os logs da execução pelo &lt;a href="https://console.aws.amazon.com/cloudwatch/home" rel="noopener noreferrer"&gt;CloudWatch&lt;/a&gt; como explicado anteriormente e ver o arquivo de output final do bucket de output!&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.amazonaws.com%2Fuploads%2Farticles%2Fz6zt9t071ednjniv1pkk.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.amazonaws.com%2Fuploads%2Farticles%2Fz6zt9t071ednjniv1pkk.png" alt="Console AWS demonstrando arquivo no bucket de output" width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Limpeza da casa
&lt;/h2&gt;

&lt;p&gt;É uma boa prática nos acostumarmos a deletar os recursos da nuvem quando não estão mais em uso. Se algum dia você não estiver mais usando uma conta free tier, isso vai te poupar de ter cobranças surpresa (pode me agradecer depois). No nosso caso, os recursos criados foram uma função Lambda e dois buckets do S3.&lt;/p&gt;

&lt;p&gt;Para remover a função, basta navegar até a &lt;a href="https://console.aws.amazon.com/lambda/home" rel="noopener noreferrer"&gt;página principal do serviço Lambda&lt;/a&gt;, selecionar a função que quer apagar e clicar em "Ações" &amp;gt; "Excluir". &lt;/p&gt;

&lt;p&gt;Para remover os buckets, vá para para a &lt;a href="https://console.aws.amazon.com/s3" rel="noopener noreferrer"&gt;página principal do S3&lt;/a&gt;, selecione o bucket e clique em "Excluir". É preciso que o bucket esteja vazio para que ele possa ser deletado. Caso não esteja, o console mostrará uma mensagem informando que é preciso esvaziá-lo. Você pode clicar em "Esvaziar bucket" para apagar todos os objetos. Após fazer isso, selecione o bucket novamente e clique em "Excluir".&lt;/p&gt;

&lt;h2&gt;
  
  
  Próximos passos
&lt;/h2&gt;

&lt;p&gt;Agora você já sabe como subir seu código na nuvem e até mesmo como montar seu primeiro sistema serverless!&lt;/p&gt;

&lt;p&gt;Uma limitação dessa aplicação que construimos é que os arquivos são convertidos para json um de cada vez, gerando vários documentos, mas e se quisermos colocar vários arquivos em um único output? Será que poderíamos subir uma pasta no S3 e converter tudo de uma vez? &lt;/p&gt;

&lt;p&gt;Deixo como exercício clonar o &lt;a href="https://github.com/gi-armani/CSVToJSONConverter" rel="noopener noreferrer"&gt;repositório&lt;/a&gt;, replicar a infraestrutura que vimos e implementar essa funcionalidade nova!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>lambda</category>
      <category>serverless</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A verdade oculta por trás do Serverless</title>
      <dc:creator>Giovana Armani</dc:creator>
      <pubDate>Wed, 04 Feb 2026 20:20:10 +0000</pubDate>
      <link>https://forem.com/giarmani/a-verdade-oculta-por-tras-do-serverless-55f7</link>
      <guid>https://forem.com/giarmani/a-verdade-oculta-por-tras-do-serverless-55f7</guid>
      <description>&lt;p&gt;Entenda de uma vez por todas o que realmente significa Serverless e porque isso fará toda a diferença no seu processo de desenvolvimento!&lt;/p&gt;




&lt;h2&gt;
  
  
  Primeiras definições
&lt;/h2&gt;

&lt;p&gt;Antes de podermos falar do que é serverless, sabemos &lt;strong&gt;o que é um servidor&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Gosto de pensar servidores como aqueles computadores muito poderosos que parecem geladeiras (vai me dizer que não?). Existem vários tipos de servidores especializados em diferentes tarefas. Eles podem armazenar, processar, gerenciar e transferir dados e arquivos, executar programas, enviar emails, disponibilizar conteúdo na internet, entre muitas outras funções.&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.amazonaws.com%2Fuploads%2Farticles%2Foqrzd08do9crj6dl368v.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.amazonaws.com%2Fuploads%2Farticles%2Foqrzd08do9crj6dl368v.png" alt="Servidor" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Evolução histórica
&lt;/h2&gt;

&lt;p&gt;Nos primórdios da computação, cada empresa dona de um software, precisava comprar e manter seu próprio servidor para rodar sua aplicação. Isso adicionava uma alta carga de trabalho porque era preciso cuidar dessas máquinas, da mesma forma que cuidamos de nossos computadores pessoais, mas em escala muito maior. Tarefas como gerenciamento do sistema operacional, atualizações de segurança, gerenciamento do sistema de arquivos, balanceamento de carga, monitoramento e registro em log eram todas tarefas que deviam ser feitas regularmente para essas máquinas gigantes e complexas.&lt;/p&gt;

&lt;p&gt;Além disso, o uso desses servidores não era nada eficiente. Imagine que a venda do seu Zé tinha um servidor para processar compras na sua loja virtual. Em momentos de pico de pedidos como Natal ou Black Friday, era preciso o poder de processamento do servidor inteiro. Já no resto do ano, o tráfego era bem mais baixo e em grande parte do tempo, só precisava de uma parte dele.&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.amazonaws.com%2Fuploads%2Farticles%2Fi0x6ur3t2ir13w614cym.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.amazonaws.com%2Fuploads%2Farticles%2Fi0x6ur3t2ir13w614cym.png" alt="Uso do servidor" width="713" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isso adicionava um custo e um trabalho desnecessário porque apesar do seu Zé estar usando somente metade da sua "geladeira", ainda é preciso fazer manutenção dela inteira.&lt;/p&gt;

&lt;p&gt;Por sorte, os provedores de computação em nuvem vieram solucionar esse problema com &lt;strong&gt;Serverless&lt;/strong&gt; (ou na tradução pro português que quase ninguém usa, computação sem servidores). Nesse modelo, a empresa de nuvem é a dona dos servidores e ela permite que outras empresas e desenvolvedores utilizem suas máquinas sob demanda através da internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como funciona a computação serverless
&lt;/h2&gt;

&lt;p&gt;Eis a mentira: por mais que o nome tente te convencer que é possível rodar software sem servidores, ainda não estamos tão avançados. Com serverless, os computadores-geladeira ainda existem, mas são completamente administrados e mantidos pela empresa provedora de nuvem. Isso permite que a gente foque em resolver problemas com código e a nuvem cuida do resto.&lt;/p&gt;

&lt;p&gt;Você pode imaginar como um serviço de lavanderia. Ao invés de comprar uma máquina de lavar, você leva suas roupas até a lavanderia, usa a máquina do tamanho que precisar, espera a roupa bater e depois paga apenas por aquela lavagem.&lt;/p&gt;

&lt;p&gt;Na computação serverless, os programas são acionados pelo que chamamos de eventos. Um &lt;strong&gt;evento&lt;/strong&gt; é um acontecimento que diz ao programa que é hora de fazer alguma tarefa, como a chegada de uma mensagem ou uma interação do usuário com a tela. No nosso exemplo da lavanderia, poderíamos considerar como evento o ato de colocar as roupas na máquina e apertar o botão de iniciar. Quando o evento for recebido, é iniciado o processamento que gera um resultado como uma escrita em banco de dados, uma geração de arquivos, uma chamada para outro serviço, etc.&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.amazonaws.com%2Fuploads%2Farticles%2Fwdtcl0fd1l2wuu396x28.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.amazonaws.com%2Fuploads%2Farticles%2Fwdtcl0fd1l2wuu396x28.png" alt="Analogia da máquina" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chamamos de &lt;strong&gt;funções serverless&lt;/strong&gt; essas unidades de código que executam tarefas específicas acionadas pelos eventos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vantagens
&lt;/h2&gt;

&lt;p&gt;Já deu pra entender que nesse modelo de computação, você não precisa administrar infraestrutura, mas vamos pensar quais são os verdadeiros benefícios disso.&lt;/p&gt;

&lt;h3&gt;
  
  
  1 Escalabilidade automática
&lt;/h3&gt;

&lt;p&gt;Com o modelo serverless, não é mais necessário fazer vários cálculos de quanto recurso seu programa vai precisar para rodar. Em casos como o do seu Zé, em que o sistema sofre várias variações de volume de requisições, a nuvem vai detectar sua necessidade automaticamente e te oferecer uma parte maior ou menor, mais ou menos potente do servidor.&lt;/p&gt;

&lt;h3&gt;
  
  
  2 Redução de custo
&lt;/h3&gt;

&lt;p&gt;Ao utilizar uma solução de computação serverless, você elimina o custo fixo de manter os servidores. Não é preciso pagar pelo espaço onde serão armazenados e nem a energia necessária para mantê-los rodando.&lt;/p&gt;

&lt;p&gt;Além disso, com a escalabilidade automática, você paga exatamente pela parte do servidor utilizada pela sua aplicação. Acabou-se o tempo de pagar por um monte de máquinas sem trabalho!&lt;/p&gt;

&lt;h3&gt;
  
  
  3 Aumento de produtividade
&lt;/h3&gt;

&lt;p&gt;Como a infraestrutura é inteiramente administrada pelo provedor de nuvem, nós devs não temos mais a responsabilidade de realizar tarefas de setup e manutenção como seleção do servidor, atualização de sistema operacional, estratégias de segurança, entre outros 🙌. Isso abre espaço pra se dedicar inteiramente no que fazemos de melhor: produzir código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Computação serverless funciona para tudo?
&lt;/h2&gt;

&lt;p&gt;Sim e não...&lt;/p&gt;

&lt;p&gt;Sabemos que pra tudo se dá um jeitinho, principalmente se você for brasileiro. Na prática é possível adaptar a computação serverless para quase qualquer cenário, mas é importante reconhecermos que ela tem algumas limitações que pode fazer com que não atenda perfeitamente algumas situações.&lt;/p&gt;

&lt;h3&gt;
  
  
  1 Cold starts
&lt;/h3&gt;

&lt;p&gt;Um dos principais desafios das funções serverless é o que chamamos de &lt;strong&gt;cold start&lt;/strong&gt; (ou traduzido, "inicialização a frio"). Como nesse modelo os servidores são disponibilizados sob demanda para as aplicações, nas primeiras chamadas a uma função serverless após um período sem chamadas, a aplicação estará "fria".&lt;/p&gt;

&lt;p&gt;No período de "aquecimento" da função, o provedor faz a preparação do ambiente para execução, inicializando o código. Isso impacta o que chamamos de &lt;strong&gt;latência&lt;/strong&gt; da função, o período de demora desde a chamada até a resposta. As chamadas depois de um período inativo serão mais demoradas do que as demais, o que pode ser um problema em sistemas que precisam de respostas rápidas.&lt;/p&gt;

&lt;p&gt;Se você quer saber mais sobre cold starts e como evitá-los pode conferir &lt;a href="https://aws.amazon.com/pt/blogs/compute/understanding-and-remediating-cold-starts-an-aws-lambda-perspective/" rel="noopener noreferrer"&gt;esse artigo&lt;/a&gt; (e me avise se gostaria de ver esse tipo de conteúdo em português 😉).&lt;/p&gt;

&lt;h3&gt;
  
  
  2 Limite de duração (Timeouts)
&lt;/h3&gt;

&lt;p&gt;No geral, funções serverless não são projetadas para códigos que ficam rodando por muito tempo. É preciso definir o tempo de timeout dela, ou seja, o tempo máximo que poderá ser executada. Isso pode ser uma desvantagem em aplicações que exigem longa duração.&lt;/p&gt;

&lt;h3&gt;
  
  
  3 Custo em aplicações com cargas constantes e previsíveis
&lt;/h3&gt;

&lt;p&gt;Custo é sempre uma preocupação quando construímos sistemas. Por oferecerem grande flexibilidade em tempo real, modelos de computação sem servidor costumam ter custos mais altos por transação quando comparado a transações em sistemas com servidor próprio. Contudo, o valor total acaba compensando quando avaliados em períodos maiores porque você só paga pelo que consome.&lt;/p&gt;

&lt;p&gt;Cada sistema vai ter que ser analisado especificamente para decidir a melhor opção: servidor dedicado ou serverless, mas para sistemas com carga constante e previsível, é possível que um servidor dedicado apresente menor custo. Para ajudar nessa decisão, você pode usar o &lt;a href="https://calculator.aws/#/" rel="noopener noreferrer"&gt;AWS Pricing Calculator&lt;/a&gt; para comparar os custos de diferentes abordagens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Veja na tabela abaixo um compilado dos principais pontos de diferença que exploramos entre aplicações serverless e aquelas com servidor reservado.&lt;/p&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;Servidor próprio&lt;/th&gt;
&lt;th&gt;Serverless&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Quem cuida do servidor&lt;/td&gt;
&lt;td&gt;Dono da aplicação&lt;/td&gt;
&lt;td&gt;Provedor de nuvem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Escalabilidade&lt;/td&gt;
&lt;td&gt;Para escalar, é preciso comprar mais servidores ou servidores mais potentes&lt;/td&gt;
&lt;td&gt;Escalabilidade automática administrada pela nuvem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custo&lt;/td&gt;
&lt;td&gt;Valor fixo de manutenção do servidor independente do uso&lt;/td&gt;
&lt;td&gt;Pague somente pelo que a aplicação consumir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tempo de resposta&lt;/td&gt;
&lt;td&gt;Aproximadamente o mesmo em todas as chamadas&lt;/td&gt;
&lt;td&gt;Primeiras chamadas após um período podem ter latência maior pelo cold start&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A computação serverless revolucionou a forma que construímos sistemas. Ela nos empodera a construir sua aplicação de forma mais rápida e eficiente, sendo uma grande aliada na administração de infraestrutura de servidores.&lt;/p&gt;

&lt;p&gt;E aí, você já conhecia computação serverless? Que tipo de aplicação você construiria dessa maneira?&lt;/p&gt;

</description>
      <category>devops</category>
      <category>programming</category>
      <category>serverless</category>
      <category>programmers</category>
    </item>
    <item>
      <title>Garanta o shape do verão com Kiro e Spec Driven Development</title>
      <dc:creator>Giovana Armani</dc:creator>
      <pubDate>Fri, 09 Jan 2026 15:16:37 +0000</pubDate>
      <link>https://forem.com/giarmani/garanta-o-shape-do-verao-com-kiro-e-spec-driven-development-43h7</link>
      <guid>https://forem.com/giarmani/garanta-o-shape-do-verao-com-kiro-e-spec-driven-development-43h7</guid>
      <description>&lt;p&gt;Como construi minha primeira aplicação com IA usando Kiro em poucos minutos e sem escrever código para acompanhar a frequência dos meus treinos.&lt;/p&gt;




&lt;p&gt;Gosto muito de me exercitar e tenho muitos objetivos físicos. Meu grande problema é que quero fazer só os treinos que gosto e ignoro os que não gosto. Todo atleta passa por isso do seu jeito, mas para mim, isso significa treinar muita perna e não treinar braço nunca.&lt;/p&gt;

&lt;p&gt;Sei que no fundo o que me falta é vergonha na cara, então pedi ajuda para o Kiro para construir uma aplicação onde eu posso registrar meus treinos para ter noção de quando estou fugindo demais. Nesse artigo, vim compartilhar como você pode usar o Kiro e Spec Driven Development para tirar suas ideias do papel de forma rápida e eficiente.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o Kiro e Spec Driven Development?
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="https://kiro.dev/docs/" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; é um editor de código com poderes de IA que te ajuda no desenvolvimento de programas. Para isso, ele oferece duas formas de interação com a ferramenta: &lt;u&gt;&lt;a href="https://www.hostinger.com/br/tutoriais/vibe-coding?utm_campaign=Generic-Tutorials-DSA-t3|NT:Se|LO:BR&amp;amp;utm_medium=ppc&amp;amp;gad_source=1&amp;amp;gad_campaignid=19588998604&amp;amp;gclid=Cj0KCQiAyP3KBhD9ARIsAAJLnnbDdrJkVcv916czlT24RwDEa-B7CODqL_7eCPy0e31ST0T1z_c0dZ0aAg9EEALw_wcB" rel="noopener noreferrer"&gt;Vibe coding&lt;/a&gt;&lt;/u&gt;, na qual o programador pede auxílio para a IA sob demanda com prompts (instruções) específicos; e &lt;u&gt;&lt;a href="https://martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html" rel="noopener noreferrer"&gt;Spec Driven Development&lt;/a&gt;&lt;/u&gt; , onde você começa o programa descrevendo seus requisitos para a IA.&lt;/p&gt;

&lt;p&gt;No modo de specs, o Kiro segue o seguinte fluxo:&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.amazonaws.com%2Fuploads%2Farticles%2Fojsmqpfemdihyeorjn0t.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.amazonaws.com%2Fuploads%2Farticles%2Fojsmqpfemdihyeorjn0t.png" alt=" " width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você guia o desenvolvimento e o Kiro te ajuda a agilizar. Você pode voltar as etapas e alterar arquivos anteriores a qualquer momento.&lt;/p&gt;

&lt;p&gt;Na IDE você ainda verá algumas funcionalidades interessantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specs:&lt;/strong&gt; onde estarão concentrados seus arquivos de requisitos, designs e tarefas para as aplicações desenvolvidas com specs;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Hooks:&lt;/strong&gt; prompts pré definidos executados autonomamente no plano de fundo. É possível usar essa feature, por exemplo, para gerar documentação ou testes a cada vez que um arquivo é salvo, otimizar performance, etc;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent steering:&lt;/strong&gt; regras que guiam o comportamento e respostas do agente através de arquivos que especificam padrões de design e código que ele deve seguir;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Servers:&lt;/strong&gt; lista todas as integrações com MCP configuradas para seu agente. Falaremos mais sobre eles em postagens futuras.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Saiba mais com a &lt;a href="https://kiro.dev/docs/specs/concepts/" rel="noopener noreferrer"&gt;documentação desses conceitos&lt;/a&gt; e veja na imagem abaixo onde achar essas funcionalidades na IDE.&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.amazonaws.com%2Fuploads%2Farticles%2Fhfupe1wm1ek3osx2e6at.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.amazonaws.com%2Fuploads%2Farticles%2Fhfupe1wm1ek3osx2e6at.png" alt=" " width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Definindo requisitos
&lt;/h2&gt;

&lt;p&gt;Se o Kiro e Spec Driven Development nos ajudam a desenvolver rapidamente cuidando da parte mais densa de escrita de código, ele nos abre espaço para ser ainda mais atentos com nossos requisitos. O segredo de trabalhar efetivamente com IA é refinar nossas habilidades de comunicação para ter certeza que o que estamos imaginando para o sistema será traduzido para código corretamente. No processo de desenvolvimento de software é recomendado definir bem os requisitos funcionais e não funcionais da sua aplicação.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Requisitos funcionais&lt;/u&gt; ditam o que a aplicação deve fazer ou como os usuários devem poder interagir com ela. Eles se relacionam aos seus objetivos de uso da aplicação. Aqui devemos listar as funcionalidades, elementos de interface gráfica, outputs esperados, entre outros.&lt;/p&gt;

&lt;p&gt;Já os &lt;u&gt;requisitos não funcionais&lt;/u&gt;, vão para um lado mais técnico. Dizem respeito a expectativas de performance, qualidade e segurança do sistema, assim como administram limitações de recursos que podem impactar a aplicação. Podemos considerar, por exemplo, requisito de tempo de resposta para determinadas operações, que podem afetar decisões de arquitetura.&lt;/p&gt;

&lt;h3&gt;
  
  
  Padrão de requisitos EARS
&lt;/h3&gt;

&lt;p&gt;EARS é o padrão de escrita de requisitos utilizado pelo Kiro. Significa Easy Approach to Requirements Syntax, ou abordagem simples para sintaxe de requisitos. Os requisitos no EARS são escritos em inglês em linguagem natural e seguem uma estrutura padrão sempre na mesma ordem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While &lt;span&gt;[optional pre-condition]&lt;/span&gt;, when &lt;span&gt;[optional trigger]&lt;/span&gt;, the &lt;span&gt;[system name]&lt;/span&gt; shall &lt;span&gt;[system response]&lt;/span&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Traduzido para o português, essa estrutura seria:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Enquanto &lt;span&gt;[pré-condição opcional]&lt;/span&gt;, quando &lt;span&gt;[gatilho opcional]&lt;/span&gt;, o &lt;span&gt;[nome do sistema]&lt;/span&gt; deve &lt;span&gt;[resposta do sistema]&lt;/span&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Enquanto &lt;span&gt;o usuário estiver logado&lt;/span&gt;, quando &lt;span&gt;o usuário clicar no botão de pagar&lt;/span&gt;, o &lt;span&gt;site da loja do seu Zé&lt;/span&gt; deve &lt;span&gt;ser redirecionado para a página de pagamento&lt;/span&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Para desenvolver com Kiro, você não precisa escrever seus requisitos assim, mas é importante entender esse padrão para conseguir fazer uma revisão cuidadosa do que ele produzir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Primeiros passos com Kiro
&lt;/h2&gt;

&lt;p&gt;Antes de mais nada, baixei e instalei o Kiro aqui: &lt;a href="https://kiro.dev/downloads/" rel="noopener noreferrer"&gt;https://kiro.dev/downloads/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em seguida, criei uma pasta local e abri na IDE do Kiro. No lado direito da IDE, selecionei Spec para começar a aplicação.&lt;/p&gt;

&lt;p&gt;Você sabia que pode falar com o Kiro em português? Comecei a aplicação oferecendo o seguinte prompt com as especificações iniciais dos meus requisitos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Por favor crie uma aplicação onde usuários possam registrar treinos feitos a cada dia. A aplicação deve conter uma UI que obedece os seguintes requisitos funcionais:

- Página principal: calendário que mostra todos os treinos realizados a cada dia. Deve ter um botão de registrar novo treino que leva para a página de registro

- Registro de treino: página com um formulário com um campo de data e uma lista com todos os tipos de treinos cadastrados. O usuário deve poder selecionar um ou mais treinos da lista ou adicionar um novo item na lista. Ao submeter o formulário, o usuário deve ser redirecionado para a página de calendário e conseguir ver os treinos que registrou

Ainda deve seguir o requisito não funcional abaixo:
- Armazenamento de dados local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calma, eu não bati a cabeça para sair fazendo loucuras como um armazenamento de dados local. Essa foi uma decisão consciente porque quero manter a aplicação o mais simples possível por ora para focarmos no desenvolvimento de código com specs e ela será evoluída aos poucos enquanto abordamos outros assuntos. Disso podemos tirar uma reflexão importante de que os &lt;strong&gt;requisitos não têm sentido por si só, mas dentro de um contexto maior do sistema&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A partir desse prompt inicial, Kiro vai criar o documento de requisitos (&lt;a href="https://github.com/gi-armani/workout-tracker/blob/main/.kiro/specs/workout-tracker/requirements.md" rel="noopener noreferrer"&gt;requirements.md&lt;/a&gt;) na pasta .kiro/specs. Ele interpreta seus requisitos iniciais e adiciona detalhes a partir deles. Nessa aplicação, por exemplo, pedi que fosse adicionado um calendário e o Kiro adicionou o requisito de que o sistema permita a navegação entre meses e anos. Esse é um ótimo momento para revisar detalhes como a experiência de navegação e tratamento de erros.&lt;/p&gt;

&lt;p&gt;Quando estava satisfeita, cliquei em "move to design phase" para prosseguir. Na sequência, Kiro criou o documento de design (&lt;a href="https://github.com/gi-armani/workout-tracker/blob/main/.kiro/specs/workout-tracker/design.md" rel="noopener noreferrer"&gt;design.md&lt;/a&gt;). Como parte dele, definiu a arquitetura, tecnologias e linguagens utilizadas, componentes e interfaces, modelos de dados e propriedades.&lt;/p&gt;

&lt;p&gt;Finalmente, segui para o plano de implementação. Ele transformou o design em uma sequência de tarefas (&lt;a href="https://github.com/gi-armani/workout-tracker/blob/main/.kiro/specs/workout-tracker/tasks.md" rel="noopener noreferrer"&gt;tasks.md&lt;/a&gt;) que revisei e aprovei para execução. Algumas tarefas são ainda marcadas como opcionais e podemos pular para um desenvolvimento mais rápido e voltar para ela depois.&lt;/p&gt;

&lt;p&gt;Veja o &lt;a href="https://github.com/gi-armani/workout-tracker" rel="noopener noreferrer"&gt;repositório com o código&lt;/a&gt; criado pelo Kiro e assista à demo abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=_njwYMvEBkY" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2F3labsnk0wnxxh53yjlvq.jpg" alt="Video Title" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Minha experiência com Kiro e Spec Driven Development foi surpreendentemente fluida e divertida!&lt;/p&gt;

&lt;p&gt;Em poucas horas, consegui sair de uma ideia simples para uma aplicação funcional, sem me perder em detalhes técnicos ou ficar travada na implementação. Pude focar exatamente no resultado que eu queria e quando queria ajustar algo, foi fácil voltar às etapas anteriores e refinar.&lt;/p&gt;

&lt;p&gt;Agora que tenho a base funcionando, posso evoluir a aplicação aos poucos - colocar um  banco de dados decente e quem sabe uma funcionalidade de lembretes automáticos que me dê bronca por pular treinos... A melhor parte é que a estrutura criada pelo Kiro facilita todas as minhas ideias mirabolantes!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quer experimentar você mesmo?&lt;/strong&gt; Baixe o Kiro em &lt;a href="https://kiro.dev/downloads/" rel="noopener noreferrer"&gt;kiro.dev&lt;/a&gt; e comece com um projeto simples que resolva algum problema seu. Pode ser um organizador de tarefas, um livro de receitas, ou qualquer coisa que você sempre quis construir mas nunca teve tempo. O importante é começar com requisitos claros e deixar o Kiro cuidar da parte técnica.&lt;/p&gt;

&lt;p&gt;Comente aqui também suas ideias de evolução para minha aplicação e vamos todos ficar bem malhados juntos (ou fingir rs)!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
