Skip to content

Instantly share code, notes, and snippets.

@instantiator
Created January 22, 2026 11:03
Show Gist options
  • Select an option

  • Save instantiator/02452c9e24993184b64f195c35b13aee to your computer and use it in GitHub Desktop.

Select an option

Save instantiator/02452c9e24993184b64f195c35b13aee to your computer and use it in GitHub Desktop.
A script to remove all but the latest version of all lambda functions found in a stack.

Deleting old lambda versions

Tip

Serverless Land offers a Lambda function cleanup step-function pattern, which can also help you to manage steady accumulation of lambda versions.

This script fills a similar niche. It will review a CloudFormation stack and remove all but the most recent N versions of all versioned lambda functions it finds there.

Context

If you have enabled Lambda versioning for your AWS deployment (perhaps because you want to be able to use Lambda SnapStart to reduce some inconveniently long cold-start times for certain runtimes, or maybe because you want to control version updates), you may be surprised to discover that all your lambda versions are preserved ad-inifinitum, and that there's no automated mechanism to delete older versions, or to set an expiry time for them.

Caching: For every function version that you publish with SnapStart enabled, you pay for the cost of caching and maintaining the snapshot.

This is especially problematic if you are using SnapStart because you may be charged for every snapshot held by SnapStart for every version of every lambda you have published. (NB. Java does not incur an additional cost.) These are also held ad-inifinitum (and do not fall under free usage levels!)

Usage

remove-old-lambda-versions.sh --stack <stack-name> [--region <region>] [--keep <keep>] [--delete]
  • <stack-name> the name of your stack (required)
  • <region> the AWS region to use (defaults to eu-west-2)
  • <keep> the number of most recent versions of the lambda to keep

The script will perform a dry run (ie. it won't delete anything) unless you also provide the -y/--delete parameter.

#!/bin/bash
usage() {
cat << EOF
Deletes all versions (except the N latest), of lambda functions belonging to a stack.
This script will only perform deletions if the -y/--delete option is set.
Options:
-s <name> --stack <name> Sets the name of the stack (required)
-r <region> --region <region> Sets the AWS region (default: eu-west-2)
-k <number> --keep <number> Number of versions to keep (default: 1)
-y --delete Set to delete lambda versions (default: not set)
-h --help Prints this help message and exits
EOF
}
# prevent paging - useful for running in automated pipelines
export AWS_PAGER=""
# defaults
REGION=eu-west-2
KEEP_VERSIONS=1
DO_IT="false"
# parameters
while [ -n "$1" ]; do
case $1 in
-s | --stack)
shift
STACK_NAME=$1
;;
-r | --region)
shift
REGION=$1
;;
-k | --keep)
shift
KEEP_VERSIONS=$1
;;
-y | --delete)
DO_IT="true"
;;
-h | --help)
usage
exit 0
;;
*)
echo -e "Unknown option $1...\n"
usage
exit 1
;;
esac
shift
done
if [ -z "$STACK_NAME" ]; then
echo "Please specify a stack name."
usage
exit 1
fi
echo "Region: $REGION"
echo "Stack: $STACK_NAME"
echo "Keep: $KEEP_VERSIONS"
echo "Delete: $DO_IT"
echo
# iterate through all stacks related to the named stack
for STACK in $(aws cloudformation list-stacks \
--region $REGION \
--output text \
--query "StackSummaries[?contains(StackName, '${STACK_NAME}') && (StackStatus=='CREATE_COMPLETE'||StackStatus=='UPDATE_COMPLETE')].[StackName]")
do
echo "Stack: $STACK..."
echo
NEXT_TOKEN=""
FETCH_MORE_STACK_RESOURCES="true"
while [ "$FETCH_MORE_STACK_RESOURCES" == "true" ]
do
STACK_RESOURCES=$(aws cloudformation list-stack-resources \
--stack-name $STACK \
--region $REGION \
${NEXT_TOKEN:+--starting-token "$NEXT_TOKEN"} \
--output json)
FUNCTION_IDs=$(echo $STACK_RESOURCES | jq -r '.StackResourceSummaries[] | select(.ResourceType=="AWS::Lambda::Function") | .PhysicalResourceId')
for FUNCTION_ID in $FUNCTION_IDs
do
FUNCTION_NAME=$(echo $STACK_RESOURCES | jq -r '.StackResourceSummaries[] | select(.PhysicalResourceId=="'$FUNCTION_ID'") | .LogicalResourceId')
echo " - Function: $FUNCTION_NAME"
VERSION_NUMBERS=$(aws lambda list-versions-by-function --function-name $FUNCTION_ID --region $REGION --output json \
| jq -r '.Versions[] | .Version' \
| grep -wv '$LATEST' \
| sort -nr)
KEEPING=$(echo "$VERSION_NUMBERS" | head -n $KEEP_VERSIONS)
DELETING=$(echo "$VERSION_NUMBERS" | tail -n +$((KEEP_VERSIONS+1)))
for KEEP_VERSION_NUMBER in $KEEPING
do
echo " - keeping version: $KEEP_VERSION_NUMBER"
done
for DELETE_VERSION_NUMBER in $DELETING
do
if [ "$DO_IT" == "true" ]; then
echo " - deleting version: $DELETE_VERSION_NUMBER"
aws lambda delete-function --function-name $FUNCTION_ID --region $REGION --qualifier $DELETE_VERSION_NUMBER
else
echo " - would delete version: $DELETE_VERSION_NUMBER"
fi
done
echo
done # current page of stack resources
# check for more resources...
NEXT_TOKEN=$(echo $STACK_RESOURCES | jq -r '.NextToken')
echo "Next token: $NEXT_TOKEN"
if [ -z "$NEXT_TOKEN" ] || [ "$NEXT_TOKEN" == "null" ]; then
FETCH_MORE_STACK_RESOURCES="false"
fi
echo "Fetch more: $FETCH_MORE_STACK_RESOURCES"
echo
done
done # all stacks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment