AWS Lambda SnapStart - Redução de até 90% no Cold Start

2024.12.23

O que é o Lambda SnapStart

O AWS Lambda SnapStart é um recurso que salva um snapshot do estado inicializado da função e o restaura durante o cold start, reduzindo significativamente o tempo de inicialização.

Linguagens Suportadas

RuntimeStatus de Suporte
Java 11, 17, 21✓ Suporte completo
Python 3.12+✓ Suportado
.NET 8✓ Suportado
Node.jsSuporte previsto

Funcionamento

Cold start normal:
1. Inicialização do container
2. Inicialização do runtime
3. Carregamento do código da função
4. Execução do código de inicialização
5. Execução do handler
→ Total: 2-10 segundos (no caso do Java)

SnapStart:
1. Restauração do snapshot em cache
2. Execução do handler
→ Total: 200-500ms

Ciclo de Vida do Snapshot

flowchart TB
    subgraph FirstDeploy["No Primeiro Deploy"]
        F1["1. Inicializar função"]
        F2["2. Capturar snapshot do estado da memória após inicialização"]
        F3["3. Salvar snapshot em cache"]
        F1 --> F2 --> F3
    end

    subgraph LaterStart["Inicializações Posteriores"]
        L1["1. Restaurar snapshot do cache"]
        L2["2. Executar hook afterRestore"]
        L3["3. Executar handler"]
        L1 --> L2 --> L3
    end

    FirstDeploy --> LaterStart

Configuração

AWS Console

Lambda > Funções > Configuração > Configuração geral > SnapStart
→ Selecionar "PublishedVersions"

AWS SAM

# template.yaml
Resources:
  MyFunction:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: java21
      Handler: com.example.Handler::handleRequest
      SnapStart:
        ApplyOn: PublishedVersions
      AutoPublishAlias: live

Terraform

resource "aws_lambda_function" "example" {
  function_name = "my-function"
  runtime       = "java21"
  handler       = "com.example.Handler::handleRequest"

  snap_start {
    apply_on = "PublishedVersions"
  }
}

resource "aws_lambda_alias" "live" {
  name             = "live"
  function_name    = aws_lambda_function.example.function_name
  function_version = aws_lambda_function.example.version
}

Hooks de Runtime

Java (CRaC)

import org.crac.Context;
import org.crac.Core;
import org.crac.Resource;

public class Handler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent>, Resource {

    private Connection dbConnection;

    public Handler() {
        // Registrar durante a inicialização
        Core.getGlobalContext().register(this);
        // Estabelecer conexão com o BD
        this.dbConnection = createConnection();
    }

    @Override
    public void beforeCheckpoint(Context<? extends Resource> context) {
        // Fechar conexão com BD antes do snapshot
        dbConnection.close();
    }

    @Override
    public void afterRestore(Context<? extends Resource> context) {
        // Restabelecer conexão com BD após restauração
        this.dbConnection = createConnection();
    }

    @Override
    public APIGatewayProxyResponseEvent handleRequest(
            APIGatewayProxyRequestEvent event,
            Context context) {
        // Lógica do handler
    }
}

Python

import boto3
from aws_lambda_powertools import Logger

logger = Logger()

# Variáveis globais (incluídas no snapshot)
db_client = None

def init_db():
    global db_client
    db_client = boto3.client('dynamodb')

# Executado na fase de inicialização
init_db()

# Caso seja necessário reinicializar após restauração
def on_restore():
    global db_client
    # Atualizar conexão
    db_client = boto3.client('dynamodb')

def handler(event, context):
    # Usar db_client restaurado do snapshot
    return db_client.get_item(...)

Pontos de Atenção

Garantir Unicidade

// Exemplo ruim: valor do snapshot é reutilizado
private final String uniqueId = UUID.randomUUID().toString();

// Exemplo bom: gerar a cada requisição
public APIGatewayProxyResponseEvent handleRequest(...) {
    String uniqueId = UUID.randomUUID().toString();
    // ...
}

Conexões de Rede

// Fechar conexões antes do snapshot
@Override
public void beforeCheckpoint(Context<? extends Resource> context) {
    httpClient.close();
    dbConnection.close();
}

// Reconectar após restauração
@Override
public void afterRestore(Context<? extends Resource> context) {
    httpClient = HttpClient.newHttpClient();
    dbConnection = dataSource.getConnection();
}

Comparação de Desempenho

Spring Boot (Java 17):
- Normal: 6.000ms
- SnapStart: 400ms (93% de redução)

Quarkus (Java 17):
- Normal: 1.500ms
- SnapStart: 200ms (87% de redução)

Python:
- Normal: 800ms
- SnapStart: 150ms (81% de redução)

Preços

Sem custo adicional
- O SnapStart em si é gratuito
- Apenas os custos normais do Lambda
- Armazenamento de snapshot também é gratuito

Melhores Práticas

✓ Otimizar código de inicialização (processamento pesado na inicialização)
✓ Implementar adequadamente hooks beforeCheckpoint/afterRestore
✓ Gerar valores que precisam de unicidade a cada requisição
✓ Atualizar pools de conexão após restauração
✓ Usar versões/aliases

Resumo

O Lambda SnapStart é um recurso que melhora dramaticamente o problema de cold start. É especialmente eficaz em runtimes com tempo de inicialização longo, como Java, e pode ser utilizado sem custos adicionais. Com a implementação adequada de hooks de runtime, pode ser usado com segurança em ambientes de produção.

← Voltar para a lista