Introduction

In the previous post, Daily Automated AWS Cost Reports by Email – Part 3, we created a Lambda function that queries the current AWS account cost using the Cost Explorer API and sends the result via SNS to an email address. Now, in this final step, we’ll schedule this Lambda function to run automatically every day at 8 PM using Amazon EventBridge.

Let’s dive into how to add the scheduled trigger to your AWS SAM template to fully automate your daily AWS cost report emails.

Ladybug Image

Resources


Architecture

First let’s remember the Architecture from the previous tutorials. The solution uses a scheduled EventBridge rule to invoke a Lambda function once per day. This function queries the AWS Cost Explorer API to retrieve the latest month-to-date cost data, grouped by service. The resulting cost report is then published to an SNS topic with Email subscription. In this tutorial we will add the EventBridge Trigger to invoke the Lambda Function once per day.

Architecture Diagram - DailyCostReportLambda

Ladybug Image

Prerequisites

Before we begin, ensure you have the following:

  • AWS Account: Active account with appropriate permissions.
  • AWS CLI: Installed and configured with your credentials.
  • SAM CLI: Installed and configured on your local machine.
  • AWS SDK for Python (Boto3): Installed in your development environment.
Ladybug Image

Step 1: Add an EventBridge Schedule to Your SAM Template

Adding a scheduled EventBridge Trigger to a Lambda Function is very easy using AWS SAM. All you need to do is to add the following section to the existing Lambda Function Resource in the SAM Template:

Events:
  DailySchedule:
    Type: Schedule
    Properties:
      Schedule: cron(0 20 * * ? *)

Now let’s incorporate this into our previously defined SAM Template. Modify your template.yaml to include a scheduled event source for your Lambda function. Here’s how the final SAM Template should look with the EventBridge rule added:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  AWS_DailyCostReport

  Sample SAM Template for AWS_DailyCostReport

Globals:
  Function:
    Timeout: 3
    MemorySize: 128

Parameters:
  EmailAddress:
    NoEcho: true
    Description: E-Mail Address for SNS Subscription
    Type: String

Resources:
  CostReportSNSTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: DailyCostReport
      Subscription:
        - Endpoint: !Ref EmailAddress
          Protocol: email

  CostReportFunction:
    Type: AWS::Serverless::Function 
    Properties:
      FunctionName: CostReportFunction
      CodeUri: lambda/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      Policies:
        - Statement:
            - Effect: Allow
              Action:
                - ce:GetCostAndUsage
              Resource: "*"
        - SNSPublishMessagePolicy:
            TopicName: !GetAtt CostReportSNSTopic.TopicName
      Environment:
        Variables:
          SNS_TOPIC_ARN: !Ref CostReportSNSTopic
      Events:
        DailySchedule:
          Type: Schedule
          Properties:
            Schedule: cron(0 19 * * ? *)

Outputs:
  CostReportFunction:
    Description: "Cost Report Lambda Function ARN"
    Value: !GetAtt CostReportFunction.Arn
  CostReportFunctionIamRole:
    Description: "Implicit IAM Role created for Cost Report function"
    Value: !GetAtt CostReportFunctionRole.Arn

The Schedule expression cron(0 19 * * ? *) corresponds to 7 PM UTC (8 PM CET) every day.

Ladybug Image

Step 2: Deploy the Updated Template

Run the following SAM CLI commands to redeploy the stack:

sam build
sam deploy

The SAM CLI will now deploy the changeset and it will look something like this:

Initiating deployment
=====================

        Uploading to AWS-DailyCostReport/123456789012345667.template  1789 / 1789  (100.00%)


Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------
Operation                LogicalResourceId        ResourceType             Replacement            
-------------------------------------------------------------------------------------------------
+ Add                    CostReportFunctionDail   AWS::Lambda::Permissio   N/A                    
                         ySchedulePermission      n                                               
+ Add                    CostReportFunctionDail   AWS::Events::Rule        N/A                    
                         ySchedule                                                                
* Modify                 CostReportFunction       AWS::Lambda::Function    False                  
-------------------------------------------------------------------------------------------------


Changeset created successfully. arn:aws:cloudformation:us-east-1:123456789:changeSet/samcli-deploy1234567890123456-123456789-123456789123456


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y


2025-05-29 13:57:25 - Waiting for stack create/update to complete

CloudFormation events from stack operations (refresh every 5.0 seconds)
-------------------------------------------------------------------------------------------------
ResourceStatus           ResourceType             LogicalResourceId        ResourceStatusReason   
-------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS       AWS::CloudFormation::S   AWS-DailyCostReport      User Initiated         
                         tack                                                                     
UPDATE_IN_PROGRESS       AWS::Lambda::Function    CostReportFunction       -                      
UPDATE_COMPLETE          AWS::Lambda::Function    CostReportFunction       -                      
CREATE_IN_PROGRESS       AWS::Events::Rule        CostReportFunctionDail   -                      
                                                  ySchedule                                       
CREATE_IN_PROGRESS       AWS::Events::Rule        CostReportFunctionDail   Resource creation      
                                                  ySchedule                Initiated              
CREATE_COMPLETE          AWS::Events::Rule        CostReportFunctionDail   -                      
                                                  ySchedule                                       
CREATE_IN_PROGRESS       AWS::Lambda::Permissio   CostReportFunctionDail   -                      
                         n                        ySchedulePermission                             
CREATE_IN_PROGRESS       AWS::Lambda::Permissio   CostReportFunctionDail   Resource creation      
                         n                        ySchedulePermission      Initiated              
CREATE_COMPLETE          AWS::Lambda::Permissio   CostReportFunctionDail   -                      
                         n                        ySchedulePermission                             
UPDATE_COMPLETE_CLEANU   AWS::CloudFormation::S   AWS-DailyCostReport      -                      
P_IN_PROGRESS            tack                                                                     
UPDATE_COMPLETE          AWS::CloudFormation::S   AWS-DailyCostReport      -                      
                         tack                                                                     
-------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
-------------------------------------------------------------------------------------------------
Outputs                                                                                         
-------------------------------------------------------------------------------------------------
Key                 CostReportFunctionIamRole                                                   
Description         Implicit IAM Role created for Cost Report function                          
Value               arn:aws:iam::1234567890123:role/AWS-DailyCostReport-                         
CostReportFunctionRole-123456789                                                             

Key                 CostReportFunction                                                          
Description         Cost Report Lambda Function ARN                                             
Value               arn:aws:lambda:us-east-1:1234567890:function:CostReportFunction        
-------------------------------------------------------------------------------------------------


Successfully created/updated stack - AWS-DailyCostReport in us-east-1

If it looks like this, the stack was deployed successfully.

Ladybug Image

Verify Changes

To verify the changes you can go the Web Console and check if the EventBridge Rule was created. To do this, navigate to the EventBridge Service, navigate to “Rules” find the newly created rule AWS-DailyCostReport-CostReportFunctionDailySchedule-xxxxxxxxxx and click on it. In that rule you can explore the Event Schedule and Targets tabs to verify that the EventBridge rule has been created correctly. It looks something like this:

AWS SNS Screenshot AWS SNS Screenshot

You should also receive an E-Mail on the specified E-Mail Address at the time specified in the schedule.

Ladybug Image

Conclusion

In this final post of the series, you learned how to use Amazon EventBridge to schedule your Lambda function to run automatically each day. With this in place, your cost reporting pipeline is now fully automated — from querying the AWS Cost Explorer API, to sending a cost summary via email, all without manual intervention.

This completes the Daily Automated AWS Cost Reports by Email series:

  1. Part 1: Developing and Testing Lambda Functions Locally
  2. Part 2: Querying Cost Explorer for Daily Cost Reports
  3. Part 3: Sending Cost Reports via Email with SNS
  4. Part 4: Scheduling with EventBridge

You can find the complete source code in the GitHub repository.

Thanks for following along! If you have questions or feedback, feel free to reach out or open an issue in the repo.

Ladybug Image

COMING UP NEXT - Learn how to manage multiple Kubernetes cluster configs cleanly using KUBECONFIG, improve CLI safety by showing your current context in the prompt, and enable autocompletion to boost productivity.

Ladybug Image
DevOpsBug-Logo

Feel free to explore my work and connect with me:

  • GitHub Repo - Explore my repositories and projects.
  • LinkedIn - Connect with me and grow your professional network.

Stay tuned to DevOpsBug for more updates, tips, and project showcases!


🙂 Happy coding!