TL;DR
A API AWS Lambda permite que desenvolvedores implantem, gerenciem e invoquem funções serverless programaticamente. Ela utiliza autenticação IAM, endpoints RESTful para gerenciamento de funções, opções de invocação assíncronas e síncronas, com limites de concorrência no nível da conta. Este guia aborda a configuração da autenticação, implantação de funções, padrões de invocação, mapeamento de fontes de eventos e estratégias de arquitetura serverless em produção.
Introdução
O AWS Lambda processa trilhões de requisições mensalmente para mais de 1 milhão de usuários ativos. Para desenvolvedores que constroem aplicações serverless, ferramentas de automação ou arquiteturas orientadas a eventos, a integração da API Lambda não é opcional — é essencial para infraestrutura como código e pipelines de CI/CD.
Esta é a realidade: equipes que gerenciam mais de 50 funções Lambda manualmente perdem de 10 a 15 horas semanais em implantações, atualizações de configuração e monitoramento. Uma integração robusta da API Lambda automatiza implantações, implementa lançamentos blue-green e permite o escalonamento dinâmico com base na demanda.
Este guia percorre o processo completo de integração da API AWS Lambda. Você aprenderá sobre autenticação IAM, criação e implantação de funções, padrões de invocação (síncrona/assíncrona), mapeamento de fontes de eventos, arquiteturas em camadas e estratégias de implantação em produção. Ao final, você terá uma integração Lambda pronta para produção.
O Que É a API AWS Lambda?
O AWS Lambda fornece uma API RESTful para gerenciar funções de computação serverless. A API gerencia:
- Criação, atualização e exclusão de funções
- Implantação de código e versionamento
- Invocação de funções (síncrona e assíncrona)
- Mapeamento de fontes de eventos (SQS, Kinesis, DynamoDB, S3)
- Gerenciamento de camadas para código compartilhado
- Configuração de alias e roteamento
- Gerenciamento de concorrência e capacidade reservada
- Integração de log e monitoramento
Principais Recursos
| Recurso | Descrição |
|---|---|
| API RESTful | Endpoints HTTPS padrão |
| Autenticação IAM | AWS Signature Version 4 |
| Invocação Assíncrona | Processamento de eventos "fire-and-forget" |
| Invocação Síncrona | Padrão de requisição-resposta |
| Fontes de Eventos | Mais de 200 integrações de serviços AWS |
| Camadas | Código e dependências compartilhados |
| Versões/Aliases | Deslocamento de tráfego e rollbacks |
| Concorrência Provisionada | Elimina cold starts |
Suporte a Runtimes do Lambda
| Runtime | Versões | Caso de Uso |
|---|---|---|
| Node.js | 18.x, 20.x | Backends de API, processamento de eventos |
| Python | 3.9, 3.10, 3.11 | Processamento de dados, inferência de ML |
| Java | 11, 17, 21 | Aplicações corporativas |
| Go | 1.x | APIs de alta performance |
| Rust | 1.x | Funções de baixa latência |
| .NET | 6, 8 | Workloads Windows |
| Ruby | 3.x | Aplicações web |
| Custom | Qualquer | Runtimes baseados em contêineres |
Visão Geral da Arquitetura da API
O Lambda usa a estrutura da API de serviço da AWS:
https://lambda.{region}.amazonaws.com/2015-03-31/
Versões da API
| Versão | Status | Caso de Uso |
|---|---|---|
| 2015-03-31 | Atual | Todas as operações Lambda |
| 2018-01-31 | API de Runtime | Interface de runtime customizada |
Primeiros Passos: Configuração da Autenticação
Passo 1: Criar Conta AWS e Usuário IAM
Antes de acessar a API:
- Visite o Console AWS
- Crie uma conta AWS
- Vá para Console IAM > Usuários > Criar Usuário
- Anexe políticas de execução Lambda
Passo 2: Gerar Credenciais IAM
Crie chaves de acesso para acesso programático:
# AWS CLI method
aws iam create-access-key --user-name lambda-deployer
# Saída: Armazene-os com segurança
{
"AccessKey": {
"AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
}
}
Nota de segurança: Armazene as credenciais com segurança:
# ~/.aws/credentials
[lambda-deployer]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# Ou use 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"
Passo 3: Entender AWS Signature Versão 4
Todas as requisições da API Lambda exigem 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);
// Task 1: Create 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}`;
// Task 2: Create 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}`;
// Task 3: Calculate 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');
// Task 4: Add authorization 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'
);
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();
};
// Uso
const functions = await lambdaRequest('/functions');
console.log(`Encontradas ${functions.Functions.length} funções`);
Alternativa: Usar o SDK da AWS
Para uso em produção, o SDK da AWS lida com a assinatura automaticamente:
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);
Gerenciamento de Funções
Criando uma Função
Crie uma função Lambda via API:
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;
};
// 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}`);
Fazendo Upload do Código Diretamente
Para funções pequenas (<50MB compactado):
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 função
// zip -r function.zip index.js node_modules/
await createFunctionWithZip('my-function', './function.zip');
Atualizando o Código da Função
Implante uma nova versão do código:
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 // Criar nova versão
});
console.log(`Atualizado para a versão: ${updated.Version}`);
Atualizando a Configuração da Função
Modifique o tempo limite, memória, ambiente:
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'
}
});
Excluindo uma Função
Remova a 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`);
};
Invocação de Funções
Invocação Síncrona (Requisição-Resposta)
Invoque a função e aguarde a 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', // Síncrono
'X-Amz-Log-Type': 'Tail' // Incluir logs
},
body: payload
});
// Analisar resposta
const result = JSON.parse(Buffer.from(response.Payload).toString());
const logs = Buffer.from(response.LogResult, 'base64').toString();
return { result, logs };
};
// Uso
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}`);
Invocação Assíncrona (Fire-and-Forget)
Invoque a função sem esperar:
const invokeAsync = async (functionName, payload) => {
const response = await lambdaRequest(`/functions/${functionName}/invocations`, {
method: 'POST',
headers: {
'X-Amz-Invocation-Type': 'Event', // Assíncrono
'X-Amz-Log-Type': 'None'
},
body: payload
});
return {
statusCode: response.StatusCode,
executionId: response['X-Amz-Execution-Id']
};
};
// Uso - 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}`);
Invocação de Teste (Dry Run)
Teste as permissões sem executar:
const dryRunInvocation = async (functionName) => {
const response = await lambdaRequest(`/functions/${functionName}/invocations`, {
method: 'POST',
headers: {
'X-Amz-Invocation-Type': 'DryRun'
}
});
return response;
};
// Uso - 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);
}
Tipos de Resposta de Invocação
| Tipo de Invocação | Comportamento | Caso de Uso |
|---|---|---|
RequestResponse |
Síncrono, espera pelo resultado | Chamadas de API, comandos CLI |
Event |
Assíncrono, fire-and-forget | Processamento de eventos, notificações |
DryRun |
Apenas testa permissões | Validação, depuração |
Gerenciamento de Versões e Aliases
Publicando Versões
Crie uma versão de função imutável:
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}`);
Criando Aliases
Crie um ponteiro nomeado para a versão:
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;
};
// Uso - Criar alias de produção
const prodAlias = await createAlias('order-processor', 'prod', '5', 'Production version');
console.log(`ARN do Alias: ${prodAlias.AliasArn}`);
Deslocamento de Tráfego com Configuração de Roteamento
Desloque gradualmente o tráfego para a nova versão:
const updateAliasWithRouting = async (functionName, aliasName, routingConfig) => {
const response = await lambdaRequest(`/functions/${functionName}/aliases/${aliasName}`, {
method: 'PUT',
body: {
RoutingConfig: {
AdditionalVersionWeights: routingConfig
}
}
});
return response;
};
// Uso - 10% do tráfego para a versão 6, 90% para a versão 5
await updateAliasWithRouting('order-processor', 'prod', {
'6': 0.1
});
// Após validação, desloque para 100%
await updateAliasWithRouting('order-processor', 'prod', {});
Casos de Uso de Alias
| Alias | Versão | Finalidade |
|---|---|---|
dev |
$LATEST | Testes de desenvolvimento |
staging |
Última testada | Validação de QA |
prod |
Versão estável | Tráfego de produção |
blue |
Prod atual | Implantações blue-green |
green |
Nova versão | Implantações blue-green |
Mapeamento de Fontes de Eventos
Criando Gatilho SQS
Conecte a fila SQS ao Lambda:
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}`);
Criando Gatilho de Stream do DynamoDB
Conecte o stream do DynamoDB ao Lambda:
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'
);
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 de banco de dados | Sim (1-1.000) |
| S3 | Eventos de objeto | Não (1 por evento) |
| EventBridge | Roteamento de eventos | Sim |
| API Gateway | APIs HTTP | Não |
| Schedule | Tarefas Cron | Não |
Gerenciamento de Camadas
Criando uma Camada
Empacote código/dependências compartilhados:
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}`);
Usando Camadas em Funções
Anexe camadas à função:
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 de camada
}
});
return response;
};
// Uso
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'
]
});
Concorrência e Escalonamento
Definindo Concorrência Reservada
Reserve capacidade para funções críticas:
const putFunctionConcurrency = async (functionName, reservedConcurrentExecutions) => {
const response = await lambdaRequest(`/functions/${functionName}/concurrency`, {
method: 'PUT',
body: {
ReservedConcurrentExecutions: reservedConcurrentExecutions
}
});
return response;
};
// Uso - Reserve 100 execuções concorrentes
await putFunctionConcurrency('order-processor', 100);
Limites de Concorrência da Conta
| Tipo de Conta | Limite Padrão | Aumento Disponível |
|---|---|---|
| Camada Gratuita | 1.000 | Sim |
| Pago conforme o uso | 1.000 | Sim |
| Corporativo | 1.000+ | Limites personalizados |
Lista de Verificação de Implantação em Produção
Antes de implantar em produção:
- [ ] Use o SDK da AWS para assinatura automática SigV4
- [ ] Implemente versionamento com aliases
- [ ] Configure concorrência reservada para funções críticas
- [ ] Configure filas de mensagens mortas (DLQ) para invocações assíncronas
- [ ] Habilite o rastreamento X-Ray para depuração
- [ ] Configure VPC para acesso ao banco de dados
- [ ] Implemente log estruturado (formato JSON)
- [ ] Configure alarmes do CloudWatch
- [ ] Use camadas para dependências compartilhadas
- [ ] Implemente estratégia de implantação blue-green
Casos de Uso do Mundo Real
Backend de API
Uma empresa SaaS constrói uma API REST serverless:
- Desafio: Tráfego variável, escalonamento imprevisível
- Solução: Lambda + API Gateway com autoescalonamento
- Resultado: 99,99% de tempo de atividade, 60% de redução de custo vs EC2
Implementação chave:
- Funções Lambda por recurso
- API Gateway para roteamento/autenticação
- DynamoDB para armazenamento de dados
- Concorrência provisionada para latência consistente
Pipeline de Processamento de Eventos
Uma plataforma de e-commerce processa pedidos:
- Desafio: Picos de pedidos durante eventos de vendas
- Solução: SQS + Lambda com processamento em lote
- Resultado: Zero pedidos perdidos, 10x gerenciamento de picos
Implementação chave:
- Fila SQS armazena pedidos em buffer
- Lambda processa 10 mensagens/lote
- DLQ para mensagens com falha
- Alertas do CloudWatch sobre a profundidade da fila
Conclusão
A API AWS Lambda oferece recursos abrangentes de computação serverless. Principais pontos:
- Autenticação IAM com assinatura SigV4 (use o SDK da AWS)
- Padrões de invocação síncrona e assíncrona
- Gerenciamento de versões e aliases para implantações
- Mapeamento de fontes de eventos para arquiteturas serverless
- Camadas para código e dependências compartilhados
- Apidog otimiza testes de API e colaboração em equipe
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 lida com a assinatura automaticamente.
Qual é a diferença entre invocação síncrona e assíncrona?
Síncrona (RequestResponse) espera a conclusão da função e retorna os resultados. Assíncrona (Event) enfileira a requisição e retorna imediatamente.
Como funcionam as versões do Lambda?
Cada versão publicada é um snapshot imutável de sua função. Use aliases para apontar para versões específicas e permitir o deslocamento de tráfego.
O que são Camadas Lambda?
Camadas empacotam código e dependências separadamente do código da função, permitindo bibliotecas compartilhadas entre várias funções.
Como reduzo os "cold starts"?
Use concorrência provisionada, pacotes de implantação menores e linguagens compiladas (Go, Rust) para funções críticas de latência.
O que é concorrência reservada?
Concorrência reservada garante slots de execução para funções específicas, prevenindo problemas de "vizinho barulhento".
Posso acionar o Lambda a partir do S3?
Sim, configure as notificações de eventos do S3 para invocar o Lambda na criação/exclusão de objetos.
