Skip to content

Instantly share code, notes, and snippets.

Created Oct 1, 2018
What would you like to do?
Lambda function to help you having clean CloudWatch log groups


If you don't set a name for your Lambda functions, AWS will choose one for you based on the following pattern: [stack_name]-[function_name]-[random_hash]. The problem is there are certain cases where your Lambda function gets a new name, e.g. if you have to redeploy your stack or if you have renamed the logical resource id of your function. Then, CloudFormation will associate a new CloudWatch log group with your Lambda function. In the end, this means you'll have a lot of unused log groups and you might need some time to figure out which one is the most recent one.


Simple use this file as a Lambda function and call it e.g. once a day. Suggestion: Have a separate maintenance stack in your AWS account where you use this function. Then you'll always have a clean set of CloudWatch log groups :-)


Copyright (c) 2018 Sebastian Hesse

const LOGS = require('aws-sdk/clients/cloudwatchlogs');
const logs = new LOGS();
const STACK_NAME = process.env.STACK_NAME;
const LAMBDA_LOG_GROUP_PREFIX = '/aws/lambda/';
const LAMBDA_RESOURCE_TYPE = 'AWS::Lambda::Function';
* Remove old CloudWatch groups which were part of the stack before, but don't have a related Lambda function anymore.
let removeOldLogGroups = function() {
const lambdaFunctionsSet = new Set();
console.log('Checking CloudWatch log groups...');
}).promise().then(res => {
let resources = res.StackResources;
let lambdaFunctions = resources.filter(value => value.ResourceType === LAMBDA_RESOURCE_TYPE);
lambdaFunctions.forEach(value => {
console.log('Current set of Lambda functions: ', lambdaFunctionsSet);
removeGroups(lambdaFunctionsSet, null).then(() => {
console.log('Removed all old CloudWatch log groups.');
}).catch(err => {
console.log('Error: ', err);
function removeGroups(lambdaFunctionsSet, nextToken) {
let params = {
if (nextToken) {
params.nextToken = nextToken;
// we need to retrieve all existing log groups first
return logs.describeLogGroups(params).promise().then(logGroups => {
// => compare each log group name with the current set of Lambda functions and remove unused groups
return Promise.all(removeGroupIfPartOfStack(lambdaFunctionsSet, logGroups)).then(() => {
if (logGroups.nextToken) {
return removeGroups(lambdaFunctionsSet, logGroups.nextToken);
function removeGroupIfPartOfStack(lambdaFunctionsSet, logGroups) {
let promises = [];
// go through all log groups and decide if we need to remove them
logGroups.logGroups.forEach(logGroup => {
let logGroupName = logGroup.logGroupName;
let lambdaName = logGroupName.replace(LAMBDA_LOG_GROUP_PREFIX, '');
// if a Lambda function does not have a fixed name, AWS set it's automatically with this pattern:
// [stack_name]-[function_name]-[random_hash]
// hence, check if this log group was somehow related to a Lambda function from the stack
// => if not and it's not used for a current Lambda function, simply remove it
if (lambdaName && lambdaName.indexOf(STACK_NAME) > -1 && !lambdaFunctionsSet.has(lambdaName)) {
logGroupName: logGroupName
}).promise().then(() => {
console.log('Removed log group for Lambda: ', logGroupName);
}).catch(err => {
console.log('Failed to remove log group for Lanbda: ', logGroupName);
return promises;
module.exports = {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment