This check flags Lambda functions running on a deprecated or end-of-support runtime, which means no more security patches and eventually no ability to update or invoke the function. Migrate to a supported runtime and pin runtime upgrades in your IaC.
A Lambda function is only as safe as the runtime it sits on. AWS publishes its own lifecycle for every managed runtime, and once a runtime reaches end of support, the language version and its dependencies stop receiving security patches. The Lensix lambda_oldruntimes check looks at every function in your account and tells you which ones are running on a runtime AWS has already deprecated or scheduled for deprecation.
If you have ever inherited an account full of functions nobody remembers deploying, this is one of the first checks worth running. Old runtimes hide in the corners of an account and quietly accumulate risk until the day AWS blocks updates and your deploys start failing.
What this check detects
The check inspects the Runtime property of each Lambda function and compares it against the AWS runtime support schedule. A function is flagged when its runtime is in one of two states:
- Deprecated — AWS no longer applies security patches, and you can no longer create new functions on that runtime. Existing functions still run, but you cannot update their code or configuration once the next deprecation phase hits.
- End of support / scheduled for deprecation — the runtime has a published deprecation date. It still works today, but the clock is ticking.
Typical offenders include older Node.js versions (nodejs14.x, nodejs16.x), Python (python3.7, python3.8), older Java and .NET releases, Go on the go1.x runtime, and Ruby 2.7.
Note: AWS runtime deprecation happens in two phases. Phase 1 blocks creating new functions on the runtime. Phase 2 blocks updating the code or configuration of existing functions. The function keeps executing through both phases, which is exactly why deprecated runtimes go unnoticed for so long.
Why it matters
The risk is not theoretical. A deprecated runtime is a frozen software stack that the rest of the world keeps finding holes in.
1. No more security patches
When a runtime hits end of support, AWS stops patching both the language interpreter and the operating system underneath it. Any CVE discovered in that version of Node.js, Python, or the underlying Amazon Linux stays unpatched on your function forever. If your function parses untrusted input, that is a direct exposure path.
2. You eventually lose the ability to deploy
Once a runtime reaches phase 2 deprecation, you cannot update the function. That sounds harmless until you need to ship an emergency fix and discover your CI pipeline throws InvalidParameterValueException because the runtime is no longer accepted. You are now forced to do a runtime migration under pressure, which is the worst possible time.
Warning: A deprecated-runtime function that you cannot update is a single point of failure with no rollback path. If it breaks, your only option is a full migration to a supported runtime, often without the original author or test coverage available.
3. Compliance and audit findings
Frameworks like SOC 2, PCI DSS, and CIS expect you to run supported, patched software. An auditor who finds production functions on an out-of-support runtime will write it up, and "it still runs fine" is not an accepted answer.
4. Dependency rot
Old runtimes drag old SDKs and libraries along with them. A function pinned to python3.7 cannot use modern boto3 features, and the AWS SDK bundled into older Node.js runtimes lacks newer service support. The longer you wait, the larger the migration delta becomes.
How to fix it
The fix is to move the function to a supported runtime. The amount of effort depends on how far behind you are and whether your code uses anything that changed between versions.
Step 1: Find every affected function
List all functions and their runtimes across a region:
aws lambda list-functions \
--query 'Functions[].{Name:FunctionName,Runtime:Runtime}' \
--output table
To sweep all regions and filter for known-deprecated runtimes:
for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
aws lambda list-functions --region "$region" \
--query "Functions[?contains(['nodejs14.x','nodejs16.x','python3.7','python3.8','ruby2.7','go1.x','dotnetcore3.1','java8'], Runtime)].{Name:FunctionName,Runtime:Runtime,Region:'$region'}" \
--output table
done
Step 2: Check the target runtime
Pick the current supported version of your language. As a rule, jump to the latest LTS rather than the next increment, so you do not repeat this migration in six months. Review the language changelog for breaking changes between your current version and the target.
Step 3: Update your code for the new runtime
Common things that break across versions:
- Node.js: the AWS SDK moved from v2 (bundled in Node 16 and earlier) to v3 (Node 18+). Import statements change from
require('aws-sdk')to modular@aws-sdk/client-*packages. - Python: minor syntax and stdlib deprecations between 3.7 and 3.12, plus dependency wheels that may need rebuilding for the new version.
- Go: the
go1.xruntime is fully retired. Functions move to theprovided.al2runtime with a bootstrap binary.
Step 4: Update the runtime
For a function whose code already works on the new version, update it directly:
Danger: Changing the runtime of a production function takes effect on the next invocation. Test in a non-production alias or stage first. If your code relies on behavior specific to the old runtime, a blind switch can cause runtime errors for live traffic.
aws lambda update-function-configuration \
--function-name my-function \
--runtime nodejs20.x
If you also need to ship updated code, package and deploy together:
zip -r function.zip .
aws lambda update-function-code \
--function-name my-function \
--zip-file fileb://function.zip
aws lambda update-function-configuration \
--function-name my-function \
--runtime python3.12
Tip: Use a published version and a versioned alias to roll out safely. Deploy the new runtime to a $LATEST test alias, run your smoke tests, then shift the production alias. If something breaks, point the alias back at the previous version and you have an instant rollback.
Step 5: Fix it in Infrastructure as Code
If you manage Lambda through Terraform, change the runtime in the resource definition so the next apply does not revert your console change:
resource "aws_lambda_function" "api" {
function_name = "api-handler"
handler = "index.handler"
runtime = "nodejs20.x" # was nodejs16.x
role = aws_iam_role.lambda.arn
filename = "function.zip"
}
For AWS SAM or CloudFormation:
{
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "api-handler",
"Runtime": "python3.12",
"Handler": "app.handler"
}
}
How to prevent it from happening again
Runtime drift is a recurring problem, not a one-time cleanup, because AWS deprecates runtimes on a schedule whether you are paying attention or not. The goal is to catch the next deprecation before it bites.
Gate runtimes in CI/CD
Add a check to your pipeline that rejects any deploy using a runtime on your blocklist. A simple example for a Terraform plan:
DEPRECATED="nodejs14.x nodejs16.x python3.7 python3.8 ruby2.7 go1.x"
for r in $DEPRECATED; do
if grep -rq "runtime *= *\"$r\"" ./infra; then
echo "Blocked: deprecated Lambda runtime $r found in IaC"
exit 1
fi
done
Enforce with policy-as-code
Use Open Policy Agent (OPA) or Checkov to enforce an allowlist of supported runtimes across every plan. A Conftest/Rego rule for a Terraform plan:
package main
allowed := {"nodejs20.x", "python3.12", "java21", "provided.al2023"}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_lambda_function"
runtime := resource.change.after.runtime
not allowed[runtime]
msg := sprintf("Lambda %s uses unsupported runtime %s", [resource.address, runtime])
}
Tip: Checkov ships a built-in policy (CKV_AWS_363 and related) for outdated Lambda runtimes. Wiring checkov -d . into your pipeline gives you runtime coverage without writing custom rules.
Subscribe to deprecation notices
AWS sends runtime deprecation notices through the Personal Health Dashboard and AWS Health events. Route Health events to a Slack channel or ticketing queue so a deprecation date never lands as a surprise.
Run continuous detection with Lensix
The lambda_oldruntimes check runs across your whole account on a schedule, so a function deployed last quarter that has since drifted into deprecation surfaces automatically instead of waiting for an audit.
Best practices
- Always target the latest LTS or current release of your language when creating new functions, so you start each function with the longest possible support window.
- Keep a runtime inventory and review it quarterly against the AWS runtime support schedule. Stale functions are easier to migrate in batches than under deadline.
- Use aliases and versions for every production function so runtime changes are reversible with a single alias shift.
- Pin runtimes in IaC, never in the console. A console-only change gets overwritten by the next apply and the function silently reverts to the old runtime.
- Test against the target runtime in CI before deploying, ideally running your unit tests inside the same runtime image AWS uses.
- Decommission dead functions. The cheapest migration is deleting a function nobody invokes. Check invocation metrics in CloudWatch before assuming a flagged function still matters.
Deprecated runtimes are one of those findings that look minor right up until they block a deploy or show up in an audit. Treat the runtime version as a dependency you own, keep it current, and gate it in your pipeline so the problem never comes back.

