DEV Community

Cover image for Como Usar AWS Lambda API para Serverless em 2026
Lucas
Lucas

Posted on • Originally published at apidog.com

Como Usar AWS Lambda API para Serverless em 2026

TL;DR

A API AWS Lambda permite automatizar o provisionamento, gerenciamento e a invocação de funções serverless. Ela utiliza autenticação IAM, endpoints RESTful para criar, atualizar, invocar e monitorar funções. Este guia mostra como configurar autenticação, fazer deploy de funções, implementar invocações síncronas e assíncronas, mapear eventos (SQS, DynamoDB, S3), gerenciar versões e aliases, e adotar práticas de produção para workloads serverless.

Experimente o Apidog hoje


Introdução

AWS Lambda processa trilhões de requisições por mês e é fundamental para quem constrói aplicações serverless, pipelines CI/CD ou automações de infraestrutura. Gerenciar funções manualmente não escala: equipes com dezenas de funções desperdiçam horas semanais com deploys e atualizações. Automatizar via API reduz erros, viabiliza blue-green deployments e permite escalonamento dinâmico.

Este tutorial cobre integração completa com a API AWS Lambda: autenticação IAM, deploy de funções, invocação (sync/async), mapeamento de eventos, gerenciamento de versões, arquitetura e checklist de produção. Ao final, você conseguirá orquestrar Lambda programaticamente, pronto para ambientes críticos.

O Que É a API AWS Lambda?

AWS Lambda fornece endpoints RESTful para:

  • Criar, atualizar e excluir funções
  • Deploy e versionamento de código
  • Invocação síncrona e assíncrona
  • Mapeamento de eventos (SQS, Kinesis, DynamoDB, S3)
  • Gerenciamento de camadas (layers)
  • Configuração de aliases e roteamento
  • Controle de concorrência
  • Integração com logs e monitoramento

Principais Recursos

Recurso Descrição
API RESTful Endpoints HTTPS padrão
Autenticação IAM AWS Signature Version 4
Invocação Assíncrona Eventos "fire-and-forget"
Invocação Síncrona Request-response
Fontes de Eventos +200 integrações AWS
Camadas Dependências compartilhadas
Versões/Aliases Rollbacks, roteamento de tráfego
Concorrência Provisionada Elimina cold starts

Suporte a Runtimes

Runtime Versões Caso de Uso
Node.js 18.x, 20.x APIs, eventos
Python 3.9, 3.10, 3.11 Dados, ML
Java 11, 17, 21 Corporativo
Go 1.x Alta performance
Rust 1.x Baixa latência
.NET 6, 8 Workloads Windows
Ruby 3.x Web
Custom Qualquer (container) Runtimes customizados

Visão Geral da Arquitetura da API

https://lambda.{region}.amazonaws.com/2015-03-31/
Enter fullscreen mode Exit fullscreen mode

Versões da API

Versão Status Caso de Uso
2015-03-31 Atual Todas as operações Lambda
2018-01-31 Runtime Runtimes customizados

Primeiros Passos: Configuração da Autenticação

Passo 1: Criar Conta AWS e Usuário IAM

  1. Acesse o Console AWS
  2. Crie uma conta (se necessário)
  3. Vá até IAM > Usuários > Criar Usuário
  4. Anexe políticas com permissões Lambda

Passo 2: Gerar Credenciais IAM

Gere chaves de acesso para automação:

aws iam create-access-key --user-name lambda-deployer
Enter fullscreen mode Exit fullscreen mode

Armazene as credenciais com segurança:

# ~/.aws/credentials
[lambda-deployer]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# Variáveis de ambiente
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="us-east-1"
Enter fullscreen mode Exit fullscreen mode

Passo 3: Entender AWS Signature Version 4

Toda chamada à API Lambda exige assinatura SigV4:

const crypto = require('crypto');

class AWSSigner {
  constructor(accessKeyId, secretAccessKey, region, service = 'lambda') {
    this.accessKeyId = accessKeyId;
    this.secretAccessKey = secretAccessKey;
    this.region = region;
    this.service = service;
  }

  sign(request, body = null) {
    const now = new Date();
    const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '');
    const dateStamp = amzDate.slice(0, 8);

    // Canonical request
    const hashedPayload = body ? crypto.createHash('sha256').update(body).digest('hex') : 'UNSIGNED-PAYLOAD';
    const canonicalUri = request.path;
    const canonicalQuerystring = request.query || '';
    const canonicalHeaders = `host:${request.host}\nx-amz-date:${amzDate}\n`;
    const signedHeaders = 'host;x-amz-date';
    const canonicalRequest = `${request.method}\n${canonicalUri}\n${canonicalQuerystring}\n${canonicalHeaders}\n${signedHeaders}\n${hashedPayload}`;

    // String to sign
    const algorithm = 'AWS4-HMAC-SHA256';
    const credentialScope = `${dateStamp}/${this.region}/${this.service}/aws4_request`;
    const hash = crypto.createHash('sha256').update(canonicalRequest).digest('hex');
    const stringToSign = `${algorithm}\n${amzDate}\n${credentialScope}\n${hash}`;

    // Signature
    const kDate = this.hmac(`AWS4${this.secretAccessKey}`, dateStamp);
    const kRegion = this.hmac(kDate, this.region);
    const kService = this.hmac(kRegion, this.service);
    const kSigning = this.hmac(kService, 'aws4_request');
    const signature = this.hmac(kSigning, stringToSign, 'hex');

    // Header
    const authorizationHeader = `${algorithm} Credential=${this.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;

    return {
      'Authorization': authorizationHeader,
      'X-Amz-Date': amzDate,
      'X-Amz-Content-Sha256': hashedPayload
    };
  }

  hmac(key, string, encoding = 'buffer') {
    return crypto.createHmac('sha256', key).update(string).digest(encoding);
  }
}

// Uso
const signer = new AWSSigner(
  process.env.AWS_ACCESS_KEY_ID,
  process.env.AWS_SECRET_ACCESS_KEY,
  'us-east-1'
);
Enter fullscreen mode Exit fullscreen mode

Passo 4: Criar Cliente da API Lambda

const LAMBDA_BASE_URL = 'https://lambda.us-east-1.amazonaws.com/2015-03-31';

const lambdaRequest = async (path, options = {}) => {
  const url = new URL(`${LAMBDA_BASE_URL}${path}`);
  const method = options.method || 'GET';
  const body = options.body ? JSON.stringify(options.body) : null;

  const signer = new AWSSigner(
    process.env.AWS_ACCESS_KEY_ID,
    process.env.AWS_SECRET_ACCESS_KEY,
    'us-east-1'
  );

  const headers = signer.sign({ method, host: 'lambda.us-east-1.amazonaws.com', path }, body);

  const response = await fetch(url.toString(), {
    method,
    headers: {
      'Content-Type': 'application/json',
      ...headers,
      ...options.headers
    },
    body
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Lambda API Error: ${error.Message}`);
  }

  return response.json();
};

// Exemplo: listar funções
const functions = await lambdaRequest('/functions');
console.log(`Encontradas ${functions.Functions.length} funções`);
Enter fullscreen mode Exit fullscreen mode

Alternativa: Usar o SDK da AWS

O SDK automatiza a assinatura e abstrai a comunicação:

const { LambdaClient, ListFunctionsCommand, CreateFunctionCommand, InvokeCommand } = require('@aws-sdk/client-lambda');

const lambda = new LambdaClient({ region: 'us-east-1' });

// Listar funções
const listCommand = new ListFunctionsCommand({});
const result = await lambda.send(listCommand);

// Criar função
const createCommand = new CreateFunctionCommand({
  FunctionName: 'my-function',
  Runtime: 'nodejs20.x',
  Role: 'arn:aws:iam::123456789012:role/lambda-execution-role',
  Handler: 'index.handler',
  Code: {
    S3Bucket: 'my-bucket',
    S3Key: 'function.zip'
  }
});

const fn = await lambda.send(createCommand);
Enter fullscreen mode Exit fullscreen mode

Gerenciamento de Funções

Criando uma Função

const createFunction = async (functionConfig) => {
  const response = await lambdaRequest('/functions', {
    method: 'POST',
    body: {
      FunctionName: functionConfig.name,
      Runtime: functionConfig.runtime || 'nodejs20.x',
      Role: functionConfig.roleArn,
      Handler: functionConfig.handler || 'index.handler',
      Code: {
        S3Bucket: functionConfig.s3Bucket,
        S3Key: functionConfig.s3Key
      },
      Description: functionConfig.description || '',
      Timeout: functionConfig.timeout || 3,
      MemorySize: functionConfig.memorySize || 128,
      Environment: {
        Variables: functionConfig.environment || {}
      },
      Tags: functionConfig.tags || {}
    }
  });

  return response;
};

// Exemplo de uso
const fn = await createFunction({
  name: 'order-processor',
  roleArn: 'arn:aws:iam::123456789012:role/lambda-execution-role',
  handler: 'index.handler',
  runtime: 'nodejs20.x',
  s3Bucket: 'my-deployments-bucket',
  s3Key: 'order-processor/v1.0.0.zip',
  description: 'Process orders from SQS queue',
  timeout: 30,
  memorySize: 512,
  environment: {
    DB_HOST: 'db.example.com',
    LOG_LEVEL: 'info'
  }
});

console.log(`Função criada: ${fn.FunctionArn}`);
Enter fullscreen mode Exit fullscreen mode

Fazendo Upload do Código Diretamente

const fs = require('fs');
const path = require('path');

const createFunctionWithZip = async (functionName, zipPath) => {
  const zipBuffer = fs.readFileSync(zipPath);
  const base64Code = zipBuffer.toString('base64');

  const response = await lambdaRequest('/functions', {
    method: 'POST',
    body: {
      FunctionName: functionName,
      Runtime: 'nodejs20.x',
      Role: 'arn:aws:iam::123456789012:role/lambda-execution-role',
      Handler: 'index.handler',
      Code: {
        ZipFile: base64Code
      }
    }
  });

  return response;
};

// Empacotar antes: zip -r function.zip index.js node_modules/
await createFunctionWithZip('my-function', './function.zip');
Enter fullscreen mode Exit fullscreen mode

Atualizando o Código da Função

const updateFunctionCode = async (functionName, updateConfig) => {
  const response = await lambdaRequest(`/functions/${functionName}/code`, {
    method: 'PUT',
    body: {
      S3Bucket: updateConfig.s3Bucket,
      S3Key: updateConfig.s3Key,
      Publish: updateConfig.publish || false
    }
  });

  return response;
};

// Uso
const updated = await updateFunctionCode('order-processor', {
  s3Bucket: 'my-deployments-bucket',
  s3Key: 'order-processor/v1.1.0.zip',
  publish: true
});

console.log(`Atualizado para a versão: ${updated.Version}`);
Enter fullscreen mode Exit fullscreen mode

Atualizando a Configuração da Função

const updateFunctionConfig = async (functionName, config) => {
  const response = await lambdaRequest(`/functions/${functionName}/configuration`, {
    method: 'PUT',
    body: {
      Runtime: config.runtime,
      Handler: config.handler,
      Description: config.description,
      Timeout: config.timeout,
      MemorySize: config.memorySize,
      Environment: {
        Variables: config.environment
      }
    }
  });

  return response;
};

// Uso
const updated = await updateFunctionConfig('order-processor', {
  timeout: 60,
  memorySize: 1024,
  environment: {
    DB_HOST: 'new-db.example.com',
    LOG_LEVEL: 'debug'
  }
});
Enter fullscreen mode Exit fullscreen mode

Excluindo uma Função

const deleteFunction = async (functionName, qualifier = null) => {
  const path = qualifier
    ? `/functions/${functionName}?Qualifier=${qualifier}`
    : `/functions/${functionName}`;

  await lambdaRequest(path, { method: 'DELETE' });
  console.log(`Função ${functionName} excluída`);
};
Enter fullscreen mode Exit fullscreen mode

Invocação de Funções

Invocação Síncrona (Requisição-Resposta)

const invokeFunction = async (functionName, payload, qualifier = null) => {
  const path = qualifier
    ? `/functions/${functionName}/invocations?Qualifier=${qualifier}`
    : `/functions/${functionName}/invocations`;

  const response = await lambdaRequest(path, {
    method: 'POST',
    headers: {
      'X-Amz-Invocation-Type': 'RequestResponse',
      'X-Amz-Log-Type': 'Tail'
    },
    body: payload
  });

  const result = JSON.parse(Buffer.from(response.Payload).toString());
  const logs = Buffer.from(response.LogResult, 'base64').toString();

  return { result, logs };
};

// Exemplo
const { result, logs } = await invokeFunction('order-processor', {
  orderId: 'ORD-12345',
  customerId: 'CUST-67890',
  items: [
    { sku: 'PROD-001', quantity: 2 },
    { sku: 'PROD-002', quantity: 1 }
  ]
});
console.log(`Resultado: ${JSON.stringify(result)}`);
console.log(`Logs:\n${logs}`);
Enter fullscreen mode Exit fullscreen mode

Invocação Assíncrona (Fire-and-Forget)

const invokeAsync = async (functionName, payload) => {
  const response = await lambdaRequest(`/functions/${functionName}/invocations`, {
    method: 'POST',
    headers: {
      'X-Amz-Invocation-Type': 'Event',
      'X-Amz-Log-Type': 'None'
    },
    body: payload
  });

  return {
    statusCode: response.StatusCode,
    executionId: response['X-Amz-Execution-Id']
  };
};

// Acionar processamento assíncrono
const result = await invokeAsync('email-sender', {
  to: 'customer@example.com',
  template: 'order-confirmation',
  data: { orderId: 'ORD-12345' }
});
console.log(`ID de invocação assíncrona: ${result.executionId}`);
Enter fullscreen mode Exit fullscreen mode

Invocação de Teste (Dry Run)

const dryRunInvocation = async (functionName) => {
  const response = await lambdaRequest(`/functions/${functionName}/invocations`, {
    method: 'POST',
    headers: {
      'X-Amz-Invocation-Type': 'DryRun'
    }
  });

  return response;
};

// Verificar permissões IAM
try {
  await dryRunInvocation('order-processor');
  console.log('Permissões de invocação OK');
} catch (error) {
  console.error('Permissão negada:', error.message);
}
Enter fullscreen mode Exit fullscreen mode

Tipos de Resposta de Invocação

Tipo de Invocação Comportamento Caso de Uso
RequestResponse Síncrono APIs, comandos CLI
Event Assíncrono, fire-and-forget Processamento/eventos
DryRun Teste de permissão Validação/depuração

Gerenciamento de Versões e Aliases

Publicando Versões

const publishVersion = async (functionName, description = null) => {
  const response = await lambdaRequest(`/functions/${functionName}/versions`, {
    method: 'POST',
    body: description ? { Description: description } : {}
  });

  return response;
};

// Uso
const version = await publishVersion('order-processor', 'v1.2.0 - Add tax calculation');
console.log(`Versão publicada: ${version.Version}`);
Enter fullscreen mode Exit fullscreen mode

Criando Aliases

const createAlias = async (functionName, aliasName, version, description = null) => {
  const response = await lambdaRequest(`/functions/${functionName}/aliases`, {
    method: 'POST',
    body: {
      Name: aliasName,
      FunctionVersion: version,
      Description: description
    }
  });

  return response;
};

// Exemplo: alias de produção
const prodAlias = await createAlias('order-processor', 'prod', '5', 'Production version');
console.log(`ARN do Alias: ${prodAlias.AliasArn}`);
Enter fullscreen mode Exit fullscreen mode

Deslocamento de Tráfego com Configuração de Roteamento

const updateAliasWithRouting = async (functionName, aliasName, routingConfig) => {
  const response = await lambdaRequest(`/functions/${functionName}/aliases/${aliasName}`, {
    method: 'PUT',
    body: {
      RoutingConfig: {
        AdditionalVersionWeights: routingConfig
      }
    }
  });

  return response;
};

// 10% tráfego para v6, 90% para v5
await updateAliasWithRouting('order-processor', 'prod', {
  '6': 0.1
});

// Finalizar rollout
await updateAliasWithRouting('order-processor', 'prod', {});
Enter fullscreen mode Exit fullscreen mode

Casos de Uso de Alias

Alias Versão Finalidade
dev $LATEST Testes de desenvolvimento
staging Última testada QA/Validação
prod Estável Produção
blue Prod atual Blue-green deployments
green Nova versão Blue-green deployments

Mapeamento de Fontes de Eventos

Criando Gatilho SQS

const createSQSEventSource = async (functionName, queueArn, batchSize = 10) => {
  const response = await lambdaRequest('/event-source-mappings', {
    method: 'POST',
    body: {
      EventSourceArn: queueArn,
      FunctionName: functionName,
      BatchSize: batchSize,
      Enabled: true
    }
  });

  return response;
};

// Uso
const mapping = await createSQSEventSource(
  'order-processor',
  'arn:aws:sqs:us-east-1:123456789012:orders-queue',
  10
);

console.log(`Fonte de evento criada: ${mapping.UUID}`);
Enter fullscreen mode Exit fullscreen mode

Criando Gatilho de Stream do DynamoDB

const createDynamoDBEventSource = async (functionName, streamArn, startingPosition = 'LATEST') => {
  const response = await lambdaRequest('/event-source-mappings', {
    method: 'POST',
    body: {
      EventSourceArn: streamArn,
      FunctionName: functionName,
      StartingPosition: startingPosition,
      BatchSize: 100,
      BisectBatchOnFunctionError: true,
      MaximumRetryAttempts: 3
    }
  });

  return response;
};

// Uso
await createDynamoDBEventSource(
  'user-analytics',
  'arn:aws:dynamodb:us-east-1:123456789012:table/Users/stream/2026-03-25T00:00:00.000'
);
Enter fullscreen mode Exit fullscreen mode

Tipos de Fontes de Eventos

Fonte Caso de Uso Suporte a Lotes
SQS Filas de mensagens Sim (1-10)
Kinesis Streams em tempo real Sim (1-10.000)
DynamoDB Streams Mudanças no DB Sim (1-1.000)
S3 Eventos de objeto Não (1 por evento)
EventBridge Roteamento Sim
API Gateway APIs HTTP Não
Schedule Tarefas Cron Não

Gerenciamento de Camadas

Criando uma Camada

const createLayer = async (layerName, layerConfig) => {
  const response = await lambdaRequest('/layers', {
    method: 'POST',
    body: {
      LayerName: layerName,
      Description: layerConfig.description,
      CompatibleRuntimes: layerConfig.runtimes,
      Content: {
        S3Bucket: layerConfig.s3Bucket,
        S3Key: layerConfig.s3Key
      }
    }
  });

  return response;
};

// Uso
const layer = await createLayer('shared-utils', {
  description: 'Shared utilities and dependencies',
  runtimes: ['nodejs20.x', 'nodejs18.x'],
  s3Bucket: 'my-layers-bucket',
  s3Key: 'shared-utils/v1.zip'
});
console.log(`ARN da Camada: ${layer.LayerArn}`);
Enter fullscreen mode Exit fullscreen mode

Usando Camadas em Funções

const createFunctionWithLayers = async (functionConfig) => {
  const response = await lambdaRequest('/functions', {
    method: 'POST',
    body: {
      FunctionName: functionConfig.name,
      Runtime: functionConfig.runtime,
      Role: functionConfig.roleArn,
      Handler: functionConfig.handler,
      Code: {
        S3Bucket: functionConfig.s3Bucket,
        S3Key: functionConfig.s3Key
      },
      Layers: functionConfig.layers // Array de ARNs
    }
  });

  return response;
};

// Exemplo
await createFunctionWithLayers({
  name: 'api-handler',
  roleArn: 'arn:aws:iam::123456789012:role/lambda-execution-role',
  handler: 'index.handler',
  runtime: 'nodejs20.x',
  s3Bucket: 'my-deployments-bucket',
  s3Key: 'api-handler/v1.0.0.zip',
  layers: [
    'arn:aws:lambda:us-east-1:123456789012:layer:shared-utils:1',
    'arn:aws:lambda:us-east-1:123456789012:layer:aws-sdk:3'
  ]
});
Enter fullscreen mode Exit fullscreen mode

Concorrência e Escalonamento

Definindo Concorrência Reservada

const putFunctionConcurrency = async (functionName, reservedConcurrentExecutions) => {
  const response = await lambdaRequest(`/functions/${functionName}/concurrency`, {
    method: 'PUT',
    body: {
      ReservedConcurrentExecutions: reservedConcurrentExecutions
    }
  });

  return response;
};

// Exemplo: reservar 100 execuções simultâneas
await putFunctionConcurrency('order-processor', 100);
Enter fullscreen mode Exit fullscreen mode

Limites de Concorrência da Conta

Tipo de Conta Limite Padrão Aumento Disponível
Camada Gratuita 1.000 Sim
Pago conforme uso 1.000 Sim
Corporativo 1.000+ Personalizável

Lista de Verificação de Implantação em Produção

  • [ ] Use o SDK AWS para assinatura SigV4 automática
  • [ ] Gerencie versões e aliases
  • [ ] Configure concorrência reservada
  • [ ] Use DLQ para invocações assíncronas
  • [ ] Habilite X-Ray para tracing
  • [ ] Configure VPC se acessar bancos de dados
  • [ ] Implemente logs estruturados (JSON)
  • [ ] Configure alarmes CloudWatch
  • [ ] Use camadas para dependências
  • [ ] Adote deploy blue-green

Casos de Uso do Mundo Real

Backend de API

  • Desafio: Tráfego variável, escalabilidade
  • Solução: Lambda + API Gateway com autoescalonamento
  • Resultado: 99,99% uptime, 60% de economia

Como implementar:

  • Funções Lambda por endpoint
  • API Gateway para roteamento/autenticação
  • DynamoDB como storage
  • Concorrência provisionada para performance

Pipeline de Processamento de Eventos

  • Desafio: Picos de pedidos em eventos
  • Solução: SQS + Lambda com batch
  • Resultado: Zero pedidos perdidos, escala 10x

Como implementar:

  • SQS para buffer de pedidos
  • Lambda processando lotes
  • DLQ para falhas
  • Alertas CloudWatch para fila

Conclusão

A API AWS Lambda é essencial para automação serverless de ponta-a-ponta. Aplique:

  • IAM + SigV4 (prefira SDK oficial)
  • Invocação síncrona/assíncrona conforme necessidade
  • Versionamento + aliases para deploy seguro
  • Mapeamento de eventos para integrar AWS
  • Camadas para dependências compartilhadas
  • Apidog otimiza testes e colaboração de APIs

Seção de Perguntas Frequentes

Como me autentico com a API Lambda?

Use credenciais AWS IAM com assinatura Signature Version 4. O SDK da AWS faz a assinatura automaticamente.

Qual é a diferença entre invocação síncrona e assíncrona?

Síncrona (RequestResponse) espera a execução e retorna resultado. Assíncrona (Event) coloca na fila e retorna imediatamente.

Como funcionam as versões do Lambda?

Cada versão publicada é imutável. Use aliases para apontar para versões específicas e gerenciar rollout de tráfego.

O que são Camadas Lambda?

Camadas empacotam dependências e bibliotecas para serem reutilizadas entre funções.

Como reduzo os "cold starts"?

Use concorrência provisionada, pacotes menores e linguagens compiladas (Go, Rust) para funções sensíveis à latência.

O que é concorrência reservada?

Garante slots de execução para funções específicas, evitando "vizinho barulhento".

Posso acionar o Lambda a partir do S3?

Sim, configure notificações de eventos do S3 para invocar funções na criação/exclusão de objetos.

Top comments (0)