Python cold starts on Lambda are dominated by import graphs and runtime init—not your handler body. Provisioned concurrency buys you warm sandboxes; lean imports and init-time priming make those sandboxes actually ready. SnapStart helps some workloads, but most API paths win faster by deleting dead imports and priming clients once per execution environment.
⚡ TL;DR: Measure
Init Durationseparately fromDuration; strip unused transitive imports; create boto3/HTTP clients in the init phase; put Provisioned Concurrency on the alias that serves production traffic; keep a canary with concurrency=0 to watch cold-start regressions. See Lambda SnapStart for Python: Pitfalls Beyond the Java Marketing and Lambda Warm Pools: Low-Latency Backends for Coding Agent Tools.
Separate cold start from business latency
CloudWatch’s Duration hides init. Use REPORT lines / EMF metrics: init_duration_ms, restore_duration_ms (SnapStart), and handler duration_ms. SLO burn should attribute cold starts to a dedicated budget.
# handler/metrics.py
import os
from aws_lambda_powertools import Metrics
from aws_lambda_powertools.metrics import MetricUnit
metrics = Metrics(namespace="Checkout", service="pay")
_COLD = {"v": True}
def mark_request():
if _COLD["v"]:
metrics.add_metric("ColdStart", unit=MetricUnit.Count, value=1)
_COLD["v"] = False
else:
metrics.add_metric("WarmStart", unit=MetricUnit.Count, value=1)
Lean the import graph
Import cost is paid on every cold start. Move heavy optional deps behind functions; avoid star imports; prefer narrow boto3 clients.
# handler/app.py — ✅ init-phase priming, lean surface
import json
import os
import boto3
_ddb = boto3.client("dynamodb")
_table = os.environ["TABLE"]
def handler(event, context):
body = json.loads(event["body"])
_ddb.put_item(TableName=_table, Item={"pk": {"S": body["id"]}})
return {"statusCode": 200, "body": "{}"}
# ❌ Cold start tax
import pandas as pd # unused in handler
import numpy as np
from mycompany.monolith import everything
Provisioned concurrency on the right alias
Pin PC to live (or weighted alias), not $LATEST. Combine with reserved concurrency bulkheads so a noisy neighbor cannot steal your warm pool—see Lambda Reserved Concurrency: Bulkheads That Protect Tenant Workloads.
# template.yaml (SAM)
Resources:
PayFn:
Type: AWS::Serverless::Function
Properties:
Runtime: python3.12
Handler: app.handler
AutoPublishAlias: live
ProvisionedConcurrencyConfig:
ProvisionedConcurrentExecutions: 20
Environment:
Variables:
TABLE: !Ref Table
Init-time priming checklist
- Create SDK clients, connection pools, and JWT validators at import time.
- Optionally touch secrets/config once (
GetSecretValue) during init; cache. - Avoid doing work that must differ per request (tenant routing).
- If using SnapStart: re-seed RNGs and refresh credentials post-restore.
- Keep package under size budgets; prefer container images only when layers hurt more than image pull.
When to stop optimizing Python
If p99 init stays >500ms after lean imports + PC, revisit SnapStart, arm64, or a Rust/Node sidecar for the hottest path—not a full rewrite. Gate that decision on measured init histograms and cost of PC vs. latency revenue. Alias traffic shifting (Lambda Alias Traffic Shifting) lets you prove the change safely.
Closing checklist
✅ Dos
– ✅ Track init vs handler duration as separate metrics
– ✅ Instantiate clients during init; reuse across invokes
– ✅ Attach Provisioned Concurrency to the production alias
– ✅ Keep a zero-PC canary for regression detection
– ✅ Pair PC with reserved concurrency bulkheads
❌ Don’ts
– ❌ Don’t put PC on $LATEST
– ❌ Don’t import pandas/ML stacks into an API Lambda “just in case”
– ❌ Don’t fetch secrets on every warm invoke
– ❌ Don’t ignore restore hooks if you enable SnapStart
– ❌ Don’t confuse Provisioned Concurrency with reserved concurrency
Related reading
- Lambda SnapStart for Python: Pitfalls Beyond the Java Marketing
- Lambda Warm Pools: Low-Latency Backends for Coding Agent Tools
- Lambda Reserved Concurrency: Bulkheads That Protect Tenant Workloads
- Lambda Alias Traffic Shifting: Automated Rollback Hooks That Fire
Last updated on September 11, 2026
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
