"Serverless" é um nome de marketing para uma mudança arquitetural real: em vez de provisionar um servidor que fica pronto para lidar com requisições, você entrega ao provedor uma função e um conjunto de eventos que devem acioná-la, e o provedor decide quando, onde e quantas vezes executá-la.
Ainda existem servidores por baixo - o nome se refere a quem os gerencia, não se eles existem.
Noções Básicas de Serverless mostra como isso se parece em código para AWS Lambda; esta página é o modelo de execução por baixo desses exemplos - o que realmente acontece entre a chegada de um evento e o retorno do seu manipulador, e por que esse modelo molda quase todas as práticas nesta seção.
Uma função serverless é executada apenas em resposta a um evento, dentro de um ambiente de execução gerenciado pelo provedor, que o provedor cria, reutiliza e eventualmente descarta em sua própria programação.
Por que Importa: O provedor - não o seu código - é o dono do ciclo de vida do processo, o que remove o custo de capacidade ociosa e a sobrecarga de operações, mas também remove suposições em que servidores Node comuns confiam, como um processo de longa duração ou um cache quente na memória.
Conceitos Chave:ambiente de execução, início frio (cold start), invocação quente (warm invocation), manipulador (handler), fonte de evento (event source), statelessness (ausência de estado).
Quando Usar: Tráfego HTTP esporádico ou intermitente, processamento em segundo plano orientado a eventos (filas, streams, trabalhos agendados) e cargas de trabalho onde pagar apenas pelo tempo real de invocação é mais importante do que uma latência previsível de poucos milissegundos.
Limitações / Compromissos: Inícios frios adicionam variância de latência que você não controla totalmente, o tempo de execução e a memória são limitados pelo provedor, e qualquer coisa que um manipulador queira persistir deve viver em um serviço de apoio externo, nunca na memória local do processo.
Tópicos Relacionados: Padrões de manipulador Lambda, mitigação de início frio, arquitetura orientada a eventos, orquestração de contêineres.
Um servidor Node tradicional é iniciado uma vez, mantém um processo ativo indefinidamente e lida com cada requisição dentro desse mesmo processo de longa duração - o que significa que caches na memória, conexões de banco de dados abertas e estado em nível de módulo sobrevivem entre as requisições.
Uma função serverless inverte isso: seu código não tem controle sobre quando um processo é iniciado, quanto tempo ele vive, ou se a próxima invocação reutiliza o mesmo.
Em vez disso, uma plataforma de função como serviço (FaaS) - AWS Lambda, Azure Functions, Google Cloud Functions - possui um ambiente de execução: uma instância de runtime isolada que a plataforma cria sob demanda, entrega uma ou mais invocações, e eventualmente desativa quando decide que o ambiente não é mais útil para manter.
Seu único contrato real com a plataforma é o manipulador (handler): uma função com uma assinatura definida que a plataforma chama uma vez por invocação, e cujo valor de retorno (ou promessa resolvida) a plataforma transforma em uma resposta ou um sinal de conclusão.
Todo o resto - criação de processo, roteamento de requisição para um ambiente disponível, dimensionamento do número de ambientes concorrentes para cima ou para baixo - é trabalho da plataforma, que é o significado real de "serverless": não a ausência de servidores, mas a ausência de sua responsabilidade em gerenciá-los.
Uma maneira simples de entender esse modelo: pense no provedor como executando um pool de trabalhadores idênticos e intercambiáveis que só aparecem quando há um trabalho anunciado, e que o provedor tem liberdade de mandar para casa no momento em que há uma calmaria.
Cada invocação se enquadra em uma de duas categorias, e a diferença entre elas é a maior fonte de variância de latência em serverless.
Um início frio (cold start) acontece quando a plataforma não tem um ambiente de execução existente pronto para o seu evento, então ela precisa criar um do zero: baixar seu pacote de implantação, iniciar o runtime da linguagem, executar qualquer código de nível superior (fase de inicialização) em seu módulo antes mesmo que seu manipulador seja alcançável, e então finalmente chamar o manipulador.
Uma invocação quente (warm invocation) acontece quando a plataforma já tem um ambiente de execução sobrando de uma invocação anterior e simplesmente chama seu manipulador novamente dentro dele - pulando todas as etapas acima, exceto a chamada do manipulador.
Evento chega
-> plataforma procura um ambiente de execução ocioso
encontrado -> invocação quente: chama o manipulador diretamente
nenhum -> início frio: cria ambiente, executa código de inicialização, então chama o manipulador
-> manipulador executa, retorna um resultado
-> ambiente permanece quente por um tempo, ou é desativado se ocioso por muito tempo
É por isso que a colocação do código dentro de um arquivo de manipulador é mais importante em serverless do que em um servidor normal: qualquer coisa declarada no nível superior do módulo (um cliente de banco de dados, um esquema de configuração analisado) é executada uma vez por ambiente, não uma vez por invocação - então criá-lo fora do manipulador permite que invocações quentes pulem esse custo, enquanto criá-lo dentro do manipulador o cobra em cada chamada.
// Executa uma vez por ambiente de execução - reutilizado em invocações quentesconst client = createDatabaseClient();export const handler = async (event: RequestEvent) => { // Executa em cada invocação - este ambiente pode ser novíssimo ou quente return client.query(event.id);};
A outra consequência desse modelo é a ausência de estado (statelessness): como você não pode prever se a próxima invocação cairá no mesmo ambiente ou em um recém-criado, qualquer estado do qual seu manipulador dependa - uma sessão, um contador, um cache - deve viver em um serviço de apoio (um banco de dados, armazenamento de objetos, um cache gerenciado) em vez de em uma variável local, ou seu código se comportará de maneira diferente dependendo de um detalhe de implementação que você não controla.
A concorrência segue a mesma lógica pela outra direção: a plataforma pode criar muitos ambientes de execução em paralelo para lidar com eventos simultâneos, que é onde serverless obtém sua história de escalabilidade elástica - mas isso também significa que seu manipulador precisa assumir que pode estar sendo executado muitas vezes, simultaneamente, contra recursos downstream compartilhados como um limite de conexão de banco de dados.
O tempo de execução e a memória não são ilimitados como são efetivamente em um servidor que você provisiona, pois o tempo de execução de cada invocação e a memória que um ambiente de execução recebe, e exceder qualquer um deles termina a invocação.
Esse limite é um limite arquitetural real, não apenas um botão de ajuste: trabalho que genuinamente precisa ser executado por horas, ou manter uma conexão persistente aberta (um WebSocket, um long-poll), não se encaixa no modelo de forma alguma e pertence a uma camada de computação sempre ativa em vez disso - veja O Modelo de Orquestração de Contêineres para essa alternativa.
A latência de início frio em si evoluiu como uma preocupação operacional de primeira classe: pacotes de implantação menores, menos importações pesadas no escopo do módulo e recursos como concorrência provisionada/reservada (mantendo um número definido de ambientes pré-aquecidos) existem especificamente para gerenciar a variância que um início frio introduz - Mitigação de Início Frio cobre as táticas concretas.
Recursos adjacentes à rede adicionam sua própria complicação: anexar uma função a uma rede privada (uma VPC, para alcançar um banco de dados privado) pode em si atrasar os inícios frios, porque a plataforma agora precisa provisionar interfaces de rede como parte da criação do ambiente - um custo que não existe para uma função que só fala com serviços públicos voltados para a internet.
A observabilidade também parece diferente aqui: não há um processo de longa duração para anexar um profiler no meio do caminho, então a depuração serverless depende fortemente de logs estruturados e rastreamento distribuído emitidos por invocação, correlacionados por um ID de requisição, em vez de inspecionar um processo em execução.
Modelo de Computação
Força
Fraqueza
Melhor Encaixe
Serverless (FaaS)
Sem custo ocioso; escala para zero e para muitos automaticamente
Inícios frios, limites de tempo de execução, sem estado persistente local
Tráfego HTTP esporádico, trabalho em segundo plano orientado a eventos, trabalhos agendados
Contêineres sempre ativos (K8s/ECS)
Latência baixa previsível; conexões de longa duração funcionam naturalmente
Paga por capacidade ociosa; você gerencia o dimensionamento e a supervisão do processo
Tráfego de base constante, WebSockets, trabalhos de longa duração
VM/servidor tradicional
Controle total sobre o ambiente de runtime
Maior carga operacional; planejamento de capacidade manual
Cargas de trabalho legadas, requisitos de runtime especializados
"Serverless significa que não há servidor executando meu código." Ainda existe um servidor - um ambiente de execução gerenciado pelo provedor - a diferença é que você nunca o provisiona, corrige ou dimensiona sozinho.
"Um início frio acontece em cada invocação." Somente quando nenhum ambiente de execução ocioso está disponível; a plataforma reutiliza ambientes existentes para invocações quentes sempre que pode, o que é o caso comum sob tráfego constante.
"O código no topo do meu arquivo de manipulador é executado em cada requisição." O código fora da função manipuladora é executado uma vez por ambiente de execução, não uma vez por invocação - ele é compartilhado entre todas as invocações quentes que esse ambiente atende.
"Funções serverless podem manter estado entre invocações como caches na memória em um servidor." Qualquer estado deve ser tratado como perdido no momento em que uma invocação termina, porque o próximo evento pode cair em um ambiente de execução diferente e recém-criado.
"Serverless é sempre mais barato do que executar contêineres." É mais barato para cargas de trabalho esporádicas ou de baixa utilização média; com tráfego alto e constante, o modelo de precificação por invocação pode custar mais do que um servidor sempre ativo dimensionado para essa mesma carga.
O que "serverless" realmente significa se ainda existem servidores?
Refere-se a quem é responsável por gerenciar o servidor, não se um existe. O provedor de nuvem lida com o provisionamento, dimensionamento e correção do ambiente de execução; você apenas fornece a função e os eventos que devem acioná-la.
O que é um ambiente de execução?
Uma instância de runtime isolada que a plataforma cria para executar sua função - ela inicia o runtime da linguagem, executa o código de nível superior do seu módulo uma vez e, em seguida, pode atender a uma ou mais invocações do manipulador antes que a plataforma eventualmente a desative.
Qual é a diferença entre um início frio e uma invocação quente?
Um início frio significa que a plataforma teve que criar um ambiente de execução totalmente novo antes de poder chamar seu manipulador, pagando o custo de inicialização do runtime e o código de inicialização do seu módulo. Uma invocação quente reutiliza um ambiente sobrando de uma chamada anterior, indo direto para o manipulador.
Por que importa onde eu crio um cliente de banco de dados no meu arquivo de manipulador?
O código no nível superior do módulo é executado uma vez por ambiente de execução e é reutilizado por todas as invocações quentes que esse ambiente atende, enquanto o código dentro da função manipuladora é executado em cada chamada. Criar recursos caros como clientes fora do manipulador evita pagar esse custo repetidamente.
Minha função pode manter estado entre invocações?
Não de forma confiável - você não pode controlar se a próxima invocação reutilizará o ambiente atual ou cairá em um novo, então qualquer estado que precise persistir pertence a um serviço de apoio externo, como um banco de dados ou cache gerenciado, não a uma variável local.
Por que as funções serverless têm limites de tempo de execução e memória?
A plataforma está gerenciando um pool compartilhado e elástico de ambientes de execução em seu nome, e um runtime ilimitado por invocação tornaria impossível dimensionar ou faturar esse pool de forma previsível. Cargas de trabalho que genuinamente precisam de execução de longa duração ou conexão persistente pertencem à computação sempre ativa em vez disso.
Como o serverless escala para lidar com picos de tráfego?
A plataforma cria ambientes de execução adicionais em paralelo à medida que eventos concorrentes chegam, em vez de rotear mais requisições através de um único processo. É também por isso que invocações concorrentes podem colocar pressão inesperada em recursos downstream como o limite de conexão de um banco de dados.
Quando o serverless NÃO se encaixa em uma carga de trabalho?
Quando você precisa de conexões de longa duração (WebSockets, long-polling), latência previsível abaixo de 10ms independentemente dos inícios frios, ou tráfego constante 24 horas por dia, onde um servidor sempre ativo custaria na verdade menos do que o preço por invocação.
Anexar uma função a uma rede privada afeta algo?
Sim - acessar um recurso privado como um banco de dados dentro de uma VPC geralmente requer que a plataforma provisione interfaces de rede como parte da criação do ambiente de execução, o que pode adicionar latência mensurável especificamente aos inícios frios.
Como a depuração é diferente sem um processo de longa duração?
Não há um processo em execução para anexar um profiler ou depurador ao vivo entre invocações, então a observabilidade serverless depende de logs estruturados e rastros distribuídos emitidos por invocação e correlacionados por um ID de requisição.
Serverless é sempre a opção mais barata em comparação com contêineres?
Não universalmente - tende a vencer para tráfego esporádico ou intermitente onde um contêiner ficaria ocioso, mas com tráfego alto e sustentado o modelo de custo por invocação pode exceder o que um servidor sempre ativo dimensionado corretamente custaria.
Qual é a unidade real que a plataforma está gerenciando - uma função, ou algo mais?
O ambiente de execução, não a definição da função em si. Sua função é apenas código que a plataforma carrega em qualquer ambiente de execução que decida criar ou reutilizar para um determinado evento.