Lambda est séduisant sur le papier — pas de serveur, facturation à la milliseconde, scalabilité automatique. En pratique, quelques pièges coûtent cher en latence, en fiabilité ou en facture.
Structure d’une fonction Lambda professionnelle
import json
import logging
import os
import boto3
from aws_lambda_powertools import Logger, Tracer, Metrics
from aws_lambda_powertools.metrics import MetricUnit
logger = Logger()
tracer = Tracer()
metrics = Metrics(namespace="MyApp")
# Initialiser les clients en dehors du handler — réutilisés entre les invocations
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['TABLE_NAME'])
@logger.inject_lambda_context(log_event=True)
@tracer.capture_lambda_handler
@metrics.log_metrics
def handler(event, context):
try:
order_id = event['pathParameters']['orderId']
with tracer.capture_method():
order = table.get_item(Key={'orderId': order_id})
if 'Item' not in order:
return {'statusCode': 404, 'body': json.dumps({'error': 'Order not found'})}
metrics.add_metric(name="OrdersRetrieved", unit=MetricUnit.Count, value=1)
return {
'statusCode': 200,
'headers': {'Content-Type': 'application/json'},
'body': json.dumps(order['Item'])
}
except Exception as e:
logger.exception("Erreur inattendue")
return {'statusCode': 500, 'body': json.dumps({'error': 'Internal server error'})}
Cold starts : comprendre et mitiger
Un cold start se produit quand Lambda doit démarrer un nouveau conteneur pour votre fonction. Il ajoute 100ms à plusieurs secondes selon le runtime et la taille du package.
Causes de cold starts lents :
- Package trop lourd (plus de 50 MB décompressé)
- Imports lourds dans le handler au lieu du module level
- VPC attaché sans interface réseau préchauffée
# ❌ Import dans le handler = import à chaque invocation froide
def handler(event, context):
import pandas as pd # pandas prend 1-2s à importer
...
# ✅ Import au niveau module = importé une seule fois par conteneur
import pandas as pd
def handler(event, context):
...
Provisioned Concurrency pour les fonctions critiques :
resource "aws_lambda_provisioned_concurrency_config" "api" {
function_name = aws_lambda_function.api.function_name
qualifier = aws_lambda_alias.live.name
provisioned_concurrent_executions = 5 # 5 conteneurs toujours chauds
}
Lambda Layers : partager les dépendances
# Créer un layer pour les dépendances Python
mkdir -p python/lib/python3.12/site-packages
pip install -r requirements.txt -t python/lib/python3.12/site-packages/
zip -r layer.zip python/
aws lambda publish-layer-version \
--layer-name myapp-dependencies \
--zip-file fileb://layer.zip \
--compatible-runtimes python3.12
resource "aws_lambda_function" "api" {
layers = [
aws_lambda_layer_version.dependencies.arn,
"arn:aws:lambda:eu-west-1:017000801446:layer:AWSLambdaPowertoolsPythonV2:67"
]
# Votre code sans dépendances = package < 1 MB = déploiement en secondes
}
Gestion des erreurs et retries
Lambda retente automatiquement les invocations asynchrones (2 fois). Pour une queue SQS, Lambda retente jusqu’à maxReceiveCount fois avant d’envoyer le message dans une Dead Letter Queue.
import json
def handler(event, context):
failed_records = []
for record in event['Records']:
try:
body = json.loads(record['body'])
process_message(body)
except TemporaryError as e:
# Erreur temporaire : on veut un retry
logger.warning(f"Erreur temporaire sur {record['messageId']}: {e}")
failed_records.append({'itemIdentifier': record['messageId']})
except PermanentError as e:
# Erreur permanente : ne pas retry, laisser passer
logger.error(f"Erreur permanente sur {record['messageId']}: {e}")
# Ne pas ajouter à failed_records → SQS supprime le message
return {'batchItemFailures': failed_records}
resource "aws_lambda_event_source_mapping" "sqs" {
function_name = aws_lambda_function.processor.arn
event_source_arn = aws_sqs_queue.orders.arn
batch_size = 10
function_response_types = ["ReportBatchItemFailures"]
destination_config {
on_failure {
destination_arn = aws_sqs_queue.orders_dlq.arn # messages non traitables
}
}
}
Notre formation AWS couvre Lambda et l’architecture serverless avec des ateliers Terraform sur des comptes réels.