O blog da AWS
Integrando Event Source Mappings com o modo de isolamento de tenants do AWS Lambda
Construir aplicações SaaS multi-tenant orientadas a eventos normalmente requer isolamento de computação entre tenants para prevenir vazamento de dados, manter limites de segurança e garantir conformidade. Tradicionalmente, você tinha que escolher entre duas abordagens: compartilhar ambientes de execução entre tenants (arriscando contaminação cruzada de estado em memória) ou gerenciar funções Lambda separadas por tenant (o que introduz sobrecarga operacional, aumentando custos e complicando implantações). Ambas as abordagens exigiam que você fizesse concessões entre segurança, complexidade operacional e eficiência de custos.
O AWS Lambda modo de isolamento de tenants com Event Source Mappings aborda essa concessão. Esta abordagem reduz a complexidade operacional, melhora sua postura de segurança e remove a necessidade de gerenciar funções separadas por tenant, tudo isso mantendo limites de isolamento estritos no nível de computação. Agora você pode construir arquiteturas orientadas a eventos usando serviços como Amazon SQS e Amazon EventBridge onde as cargas de trabalho de cada tenant são executadas em ambientes de execução dedicados, mas você gerencia apenas uma única função Lambda.
Nesta publicação, você aprenderá como propagar a identidade do tenant a partir de payloads de eventos, implementar permissões IAM para invocações isoladas por tenant, aplicar estratégias de validação para verificar o contexto do tenant e usar um mecanismo de roteamento leve que invoca backends isolados por tenant. O código de exemplo completo demonstrando este padrão está disponível no repositório de exemplos da AWS.
Entendendo o modo de isolamento de tenants do Lambda
O modo de isolamento de tenants do AWS Lambda estende o modelo de execução do Lambda introduzindo roteamento de invocações com reconhecimento de tenant. Em vez de reutilizar ambientes de execução em todas as invocações de uma função, o Lambda associa cada ambiente de execução a um identificador de tenant específico. Quando uma nova solicitação é recebida, o Lambda a roteia para um ambiente existente para aquele tenant específico ou cria um novo se nenhum existir.
Isso simplifica como você constrói sistemas SaaS multi-tenant, mantendo limites de isolamento no nível de computação. Ambientes de execução nunca são compartilhados entre tenants, mas ainda são reutilizados dentro do mesmo tenant para máxima eficiência. Isso significa que você pode armazenar em cache com segurança configurações específicas do tenant, como feature flags ou strings de conexão de banco de dados, sem adicionar lógica de isolamento manualmente em seu código.
Para usar o modo de isolamento de tenants, cada invocação deve incluir um parâmetro de ID do tenant. Para invocações síncronas diretas, como as originadas do Amazon API Gateway ou AWS SDKs, você o passa usando o cabeçalho X-Amz-Tenant-Id, conforme descrito no blog de lançamento e na documentação do serviço. O serviço Lambda usa este cabeçalho para rotear a invocação para ambientes de execução específicos do tenant. Dentro do seu manipulador de função, o ID do tenant está disponível usando a propriedade context.tenantId, para que você possa implementar lógica com reconhecimento de tenant.
export const handler = async (event, context) => {
const tenantId = context.tenantId;
// Tenant-specific business logic here
console.log(`Processing request for tenant: ${tenantId}`);
};
Figura 2. Acessando o ID do tenant a partir do manipulador de função.
Ao usar o API Gateway, você pode extrair o valor do ID do tenant dos metadados da solicitação recebida, como cabeçalhos HTTP, parâmetros de caminho, parâmetros de consulta ou claims JWT, e mapeá-lo diretamente para o X-Amz-Tenant-Id downstream na configuração de solicitação de integração do API Gateway. Consulte o blog de lançamento para orientações detalhadas.
Este modelo funciona bem para invocações diretas e síncronas. No entanto, muitas aplicações Serverless dependem de padrões orientados a eventos, onde o Lambda é invocado através de Event Source Mappings.
Usando o modo de isolamento de tenants com fontes de eventos
Muitas aplicações Serverless usam arquiteturas orientadas a eventos construídas em serviços como Amazon SQS, Amazon EventBridge, Amazon Kinesis ou Amazon DynamoDB Streams. Nesses casos, o Lambda é invocado por um Event Source Mapping (ESM), que pesquisa a fonte de eventos e invoca sua função quando novos eventos chegam.
Com esses serviços, você normalmente encontrará a identidade do tenant incorporada no payload ou metadados do evento – por exemplo, no corpo de uma mensagem SQS ou no detalhe de um evento EventBridge. Cada fonte de evento tem seu próprio esquema de payload. Abaixo estão exemplos de payloads ao usar SQS e EventBridge, onde você pode ver o parâmetro tenantId presente no payload.
Corpo da mensagem SQS:
{
"tenantId": "TenantA",
"orderId": "ord-12345",
"eventType": "ORDER_PLACED",
"payload": { ... }
}
Detalhe do evento EventBridge:
{
"source": "com.myapp.orders",
"detail-type": "OrderPlaced",
"detail": {
"tenantId": "TenantA",
"orderId": "ord-12345"
}
}
No entanto, as fontes de eventos não fornecem um mecanismo integrado para mapear propriedades de mensagens para cabeçalhos HTTP. Como resultado, se você tentar invocar uma função com o modo de isolamento de tenants ativado diretamente de um mapeamento de fonte de eventos, ele falhará porque o ID do tenant não é propagado como o cabeçalho X-Amz-Tenant-Id. A seção a seguir descreve como abordar isso e integrar ESMs com funções Lambda isoladas por tenant.
Propagando a identidade do tenant com Event Source Mappings
Para propagar a identidade do tenant a partir de mensagens ESM, você pode introduzir um componente de roteamento – uma função Lambda leve que fica entre a fonte de eventos e sua função backend isolada por tenant. Sua função de roteamento recebe eventos do ESM, extrai o ID do tenant de cada mensagem e invoca sua função backend usando a API Invoke do Lambda, passando o cabeçalho X-Amz-Tenant-Id necessário. Veja o diagrama a seguir para um exemplo de arquitetura usando SQS ESM.
Figura 3. Propagando o ID do tenant de mensagens SQS para o Lambda com o modo de isolamento de tenants ativado
Você não precisa ativar o modo de isolamento de tenants na própria função de roteamento – ela age como um despachante sem estado. Sua função backend multi-tenant, que contém sua lógica de negócios principal, é executada com o modo de isolamento de tenants ativado e recebe invocações adequadamente delimitadas e com reconhecimento de tenant. Este padrão mantém o isolamento de tenants na camada backend enquanto preserva um modelo de ingestão de eventos compartilhado.
O exemplo a seguir ilustra uma função de roteamento que processa mensagens SQS recebidas, extrai o ID do tenant de cada corpo de mensagem e invoca sua função backend com o contexto de tenant apropriado. Este exemplo assume que MessageGroupId é usado para transportar o identificador do tenant, o que garante que mensagens do mesmo tenant sejam processadas em ordem quando você está usando filas FIFO.
export const handler = async (event) => {
for (const record of event.Records) {
const body = record.body;
const messageGroupId = record.attributes?.MessageGroupId;
const command = new InvokeCommand({
FunctionName: BACKEND_FUNCTION_NAME,
InvocationType: 'Event',
TenantId: messageGroupId,
Payload: Buffer.from(body)
});
await lambdaClient.send(command);
}
}
Figura 4. Roteando mensagens SQS para uma função Lambda com o modo de isolamento de tenants ativado
O exemplo a seguir ilustra como você pode alcançar a mesma funcionalidade de roteamento ao processar eventos EventBridge.
export const handler = async (event) => {
const tenantId = event.detail?.tenantId;
if (!tenantId) {
throw new Error(`Missing tenantId in EventBridge event: ${JSON.stringify(event)}`);
}
const command = new InvokeCommand({
FunctionName: BACKEND_FUNCTION_NAME,
InvocationType: 'Event',
TenantId: tenantId,
Payload: JSON.stringify(event.detail),
});
await lambdaClient.send(command);
};
Figura 5. Roteando eventos EventBridge para uma função Lambda com o modo de isolamento de tenants ativado
Permissões IAM
A função de execução da sua função de roteamento precisa de permissão para:
- Pesquisar a fonte de eventos: Você pode aplicar esta política à função de execução da sua função ou como uma política de recurso na própria fonte de eventos.
- Invocar a função backend downstream: Além disso, sua função de roteador requer a permissão lambda:InvokeFunction delimitada ao ARN da sua função backend.
Abaixo está um exemplo de política de função de execução para permitir que a função de roteador pesquise de uma fila SQS
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"sqs:ReceiveMessage",
"sqs:DeleteMessage",
"sqs:GetQueueAttributes"
],
"Resource": "arn:aws:sqs:us-east-1:123456789012:my-queue"
}]
}
Abaixo está um exemplo de política de função de execução para permitir que a função de roteador invoque a função backend
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-backend-function"
}]
}
Figura 6. Permissões IAM usadas para implementar o mecanismo de função de roteador de ID de tenant.
Melhores práticas e considerações
Ao implementar o padrão descrito nesta publicação, mantenha essas considerações importantes em mente em relação à validação, escalabilidade e design geral do sistema.
Valide a identidade do tenant antes da invocação. A identidade do tenant vem de payloads de eventos, você não deve assumir automaticamente que é confiável. Veja como proteger seu sistema:
- Valide payloads recebidos e rejeite mensagens com IDs de tenant ausentes, malformados ou não autorizados na camada de roteamento antes de invocar sua função backend
- Mantenha um registro de tenants autoritativo e valide IDs de tenants recebidos contra ele
- Use filas de mensagens mortas (DLQs) em suas filas SQS para capturar mensagens que falham na validação para investigação e reprodução
- Ao usar EventBridge Pipes, use a etapa de enriquecimento para validar ou normalizar IDs de tenants antes que eles cheguem à sua função de roteamento
- Ative resposta de lote parcial para ESMs aplicáveis, como SQS, para que sua função de roteamento possa relatar falhas de mensagens individuais sem falhar o lote inteiro
Planeje considerações de escalabilidade. O modo de isolamento de tenants cria ambientes de execução separados por tenant. Isso pode aumentar o número de cold starts em comparação com ambientes compartilhados. Cada tenant consome simultaneidade independentemente, então monitore seu uso e solicite aumentos de cota à medida que sua base de tenants cresce.
Otimize a função de roteamento. Sua função de roteamento introduz um segmento de invocação adicional. Use invocação assíncrona (InvocationType: ‘Event’) para reduzir o tempo de espera ocioso e dimensione sua função adequadamente.
Entenda os limites de permissão. Os tenants compartilham a função de execução da sua função backend. Se você precisar de permissões refinadas por tenant, considere propagar credenciais delimitadas por tenant (por exemplo, usando AWS STS AssumeRole) do segmento upstream.
Código de exemplo
Um projeto de exemplo completo e implantável demonstrando este padrão – incluindo funções de roteamento SQS, uma função backend isolada por tenant e infraestrutura AWS SAM – está disponível neste repositório GitHub. Siga as instruções no README.md para provisionar o projeto de exemplo em sua conta
Conclusão
O modo de isolamento de tenants do Lambda introduz isolamento de computação entre tenants para suas aplicações SaaS multi-tenant, roteando cada invocação para um ambiente de execução específico do tenant. Quando você combina isso com arquiteturas orientadas a eventos construídas em serviços como SQS, EventBridge e Kinesis, o padrão de função de roteamento descrito nesta publicação permite que você propague a identidade do tenant a partir de payloads de eventos e invoque seu backend isolado por tenant com o contexto correto.
Esta abordagem estende o modo de isolamento de tenants para suas cargas de trabalho assíncronas sem alterar sua lógica de negócios principal. Você mantém o isolamento de ambiente de execução por tenant enquanto continua a usar as integrações nativas de fonte de eventos do Lambda, modelo de escalabilidade e ferramentas operacionais. Juntos, esses padrões fornecem uma base prática para construir aplicações SaaS multi-tenant orientadas a eventos seguras e escaláveis na AWS.
Próximos passos: Considere estender este padrão para outras fontes de eventos como Kinesis Data Streams ou DynamoDB Streams. Você também pode explorar a combinação desta abordagem com AWS Step Functions para orquestrar fluxos de trabalho multi-tenant complexos mantendo limites de isolamento de tenants.
Siga os links abaixo para saber mais:
- Documentação de Isolamento de Tenants do Lambda
- Construindo aplicações SaaS multi-tenant com o novo modo de isolamento de tenants do AWS Lambda
- Event Source Mappings do Lambda
- Referência da API Invoke do Lambda
Este conteúdo foi traduzido da publicação original do blog, que pode ser encontrado aqui.
