<!doctype html><html lang=en-us dir=ltr><head><meta charset=utf-8><meta name=viewport content='width=device-width,initial-scale=1'><meta name=description content="Step-by-step guide on How to Setup and Run Crons With Labda in Aws and Eventsbridge"><meta name=keywords content="aws,lambda,eventsbridge"><title>How to Setup and Run Crons With Lambda in Aws and Eventsbridge</title><link rel=canonical href=https://citizix.com/how-to-setup-and-run-aws-lambda-as-crons-with-eventsbridge.md><link rel=preconnect href=https://fonts.googleapis.com><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=preload as=style href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap"><link rel=stylesheet href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap"><link rel=stylesheet href=/scss/style.min.1dd6d55a016742a5da21ea43c61b8b477b506b7b579a863ca53e4ecd405ec690.css><meta name=p:domain_verify content="f2a4f90799200a5fbf523e938eb3cc4c"><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9201847173572708" crossorigin=anonymous></script><script>(function(e,t,n,s,o){e[s]=e[s]||[],e[s].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var a=t.getElementsByTagName(n)[0],i=t.createElement(n),r=s!="dataLayer"?"&l="+s:"";i.async=!0,i.src="https://www.googletagmanager.com/gtm.js?id="+o+r,a.parentNode.insertBefore(i,a)})(window,document,"script","dataLayer","GTM-KMW4HCHN")</script><meta property='og:title' content="How to Setup and Run Crons With Lambda in Aws and Eventsbridge"><meta property='og:description' content="Step-by-step guide on How to Setup and Run Crons With Labda in Aws and Eventsbridge"><meta property='og:url' content='https://citizix.com/how-to-setup-and-run-aws-lambda-as-crons-with-eventsbridge.md'><meta property='og:site_name' content='Citizix, The Best blog for Linux, Opensource, Devops, Cloud and all things awesome tech.'><meta property='og:type' content='article'><meta property='article:section' content='Post'><meta property='article:tag' content='lambda'><meta property='article:tag' content='aws'><meta property='article:tag' content='eventsbridge'><meta property='article:tag' content='automations'><meta property='article:published_time' content='2025-04-01T15:46:25+03:00'><meta property='article:modified_time' content='2026-06-06T22:48:02+03:00'><meta name=twitter:site content="@citizixdotcom"><meta name=twitter:creator content="@citizixdotcom"><meta name=twitter:title content="How to Setup and Run Crons With Lambda in Aws and Eventsbridge"><meta name=twitter:description content="Step-by-step guide on How to Setup and Run Crons With Labda in Aws and Eventsbridge"><script async src="https://www.googletagmanager.com/gtag/js?id=G-3N524KGTGT"></script><script>var doNotTrack=!1,dnt=navigator.doNotTrack||window.doNotTrack||navigator.msDoNotTrack,doNotTrack=dnt=="1"||dnt=="yes";if(!doNotTrack){window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag("js",new Date),gtag("config","G-3N524KGTGT")}</script><script type=application/ld+json>{"@context":"https://schema.org","@type":"Article","headline":"\"How to Setup and Run Crons With Lambda in Aws and Eventsbridge\"","description":"\"Step-by-step guide on How to Setup and Run Crons With Labda in Aws and Eventsbridge\"","image":{"@type":"ImageObject","url":"https:\/\/citizix.com\/og-default.png","width":1200,"height":630},"author":{"@type":"Person","name":"\"Eutychus Towett\"","url":"\"https://citizix.com/about-us/\""},"publisher":{"@type":"Organization","name":"\"Citizix, The Best blog for Linux, Opensource, Devops, Cloud and all things awesome tech.\"","logo":{"@type":"ImageObject","url":"https:\/\/citizix.com\/android-chrome-512x512.png","width":512,"height":512}},"datePublished":"\"2025-04-01T15:46:25+03:00\"","dateModified":"\"2026-06-06T22:48:02+03:00\"","mainEntityOfPage":{"@type":"WebPage","@id":"\"https://citizix.com/how-to-setup-and-run-aws-lambda-as-crons-with-eventsbridge.md\""},"keywords":"[\"aws\",\"lambda\",\"eventsbridge\"]","wordCount":1173,"articleSection":"\"Post\"","articleBody":"\"Automation is at the heart of reliable cloud systems. Whether you want to fetch weather data, clean logs, update caches, or ping a health endpoint, scheduled tasks (aka cron jobs) are essential.\\nTraditionally, cron jobs lived on servers. But in the cloud-native world, we aim to make our tasks serverless, secure, and scalable. Enter:\\nAWS Lambda — for running lightweight, event-driven functions. Amazon EventBridge (formerly CloudWatch Events) — for triggering those functions on a schedule (like crontab). In this guide, we’ll explore how to:\\nPackage a Python script for AWS Lambda Run it every 6 hours using EventBridge Automate deployment with a Makefile Clean up all resources when you’re done Let’s dive in.\\nThe Code Logic Let’s say we have a Python script that:\\nFetches weather data from WeatherAPI Sends that data to a debug API endpoint for processing or logging Here’s our logic saved in src/script.py:\\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 import json import os import requests def get_weather_data(city=\\u0026#34;Nairobi\\u0026#34;): api_key = os.environ.get(\\u0026#34;WEATHERAPI_KEY\\u0026#34;, \\u0026#34;e35b01c9046641c2af095849252503\\u0026#34;) url = f\\u0026#34;http://api.weatherapi.com/v1/current.json?key={api_key}\\u0026amp;q={city}\\u0026#34; try: response = requests.get(url) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f\\u0026#34;Error fetching weather data: {e}\\u0026#34;) return None def send_to_jsonplaceholder(data): url = \\u0026#34;https://stage-opsman-api.citizix.com/debug-request\\u0026#34; payload = { \\u0026#34;title\\u0026#34;: f\\u0026#34;Weather Report for {data[\\u0026#39;location\\u0026#39;][\\u0026#39;name\\u0026#39;]}\\u0026#34;, \\u0026#34;body\\u0026#34;: f\\u0026#34;Temperature: {data[\\u0026#39;current\\u0026#39;][\\u0026#39;temp_c\\u0026#39;]}°C, Conditions: {data[\\u0026#39;current\\u0026#39;][\\u0026#39;condition\\u0026#39;][\\u0026#39;text\\u0026#39;]}, Humidity: {data[\\u0026#39;current\\u0026#39;][\\u0026#39;humidity\\u0026#39;]}%\\u0026#34;, \\u0026#34;userId\\u0026#34;: 1 } try: response = requests.post(url, json=payload) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f\\u0026#34;Error sending data: {e}\\u0026#34;) return None def main(): city = os.environ.get(\\u0026#34;WEATHER_CITY\\u0026#34;, \\u0026#34;Nairobi\\u0026#34;) weather_data = get_weather_data(city) if weather_data: print(f\\u0026#34;Successfully retrieved weather data for {city}\\u0026#34;) result = send_to_jsonplaceholder(weather_data) if result: print(f\\u0026#34;Successfully sent data to JSONPlaceholder API\\u0026#34;) print(f\\u0026#34;Response: {json.dumps(result, indent=2)}\\u0026#34;) else: print(\\u0026#34;Failed to send data to JSONPlaceholder API\\u0026#34;) else: print(f\\u0026#34;Failed to retrieve weather data for {city}\\u0026#34;) if __name__ == \\u0026#34;__main__\\u0026#34;: main() Lambda Entry Point We wrap this in a Lambda-compatible handler in src/main.py:\\n1 2 3 4 5 6 from script import main def handler(event, context): main() return {\\u0026#39;statusCode\\u0026#39;: 200} This is the file AWS Lambda will call when the function is triggered.\\nPackaging the Code To make Lambda understand your code:\\nAdd dependencies in requirements.txt: 1 requests Install them locally into src/: 1 pip install -r requirements.txt -t ./src Package the folder: 1 cd src \\u0026amp;\\u0026amp; zip -r ../make-health-check.zip . This ZIP will be uploaded to AWS as your Lambda function code.\\nCreating IAM Role for Lambda AWS Lambda needs permissions to run. So, we create a role and attach basic execution permissions:\\nTrust policy 1 2 3 4 5 6 7 8 9 10 11 12 13 14 cat \\u0026gt; trust-policy.json \\u0026lt;\\u0026lt; EOF { \\u0026#34;Version\\u0026#34;: \\u0026#34;2012-10-17\\u0026#34;, \\u0026#34;Statement\\u0026#34;: [ { \\u0026#34;Effect\\u0026#34;: \\u0026#34;Allow\\u0026#34;, \\u0026#34;Principal\\u0026#34;: { \\u0026#34;Service\\u0026#34;: \\u0026#34;lambda.amazonaws.com\\u0026#34; }, \\u0026#34;Action\\u0026#34;: \\u0026#34;sts:AssumeRole\\u0026#34; } ] } EOF Create Iam role\\n1 aws iam create-role --role-name MakeHealthCheckRole --assume-role-policy-document file://trust-policy.json Attach basic execution policy\\n1 aws iam attach-role-policy --role-name MakeHealthCheckRole --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Get role arn\\n1 aws iam get-role --role-name MakeHealthCheckRole --query \\u0026#39;Role.Arn\\u0026#39; --output text Deploying the Lambda Function Use the zipped code to create the Lambda function:\\n1 2 3 4 5 6 7 8 9 zip -r make-monitor.zip . aws lambda create-function \\\\ --function-name MakeHealthCheck \\\\ --zip-file fileb://make-monitor.zip \\\\ --handler main.handler \\\\ --runtime python3.12 \\\\ --role arn:aws:iam::\\u0026lt;your-account-id\\u0026gt;:role/MakeHealthCheckRole \\\\ --timeout 30 Make sure to replace \\u0026lt;your-account-id\\u0026gt; with your real AWS account number.\\nSetting Up a Cron with EventBridge AWS EventBridge allows us to run the Lambda every 6 hours using a cron expression:\\n1 2 3 aws events put-rule \\\\ --name MakeHealthCheckSchedule \\\\ --schedule-expression \\u0026#34;cron(0 0/6 * * ? *)\\u0026#34; This runs the function at 00:00, 06:00, 12:00, and 18:00 UTC daily.\\nGive EventBridge Permission to Trigger Lambda Add permission for CloudWatch to invoke Lambda\\n1 2 3 4 5 6 aws lambda add-permission \\\\ --function-name MakeHealthCheck \\\\ --statement-id MakeHealthCheckSchedule \\\\ --action lambda:InvokeFunction \\\\ --principal events.amazonaws.com \\\\ --source-arn $(aws events describe-rule --name MakeHealthCheckSchedule --query \\u0026#39;Arn\\u0026#39; --output text) Create Target Create target JSON file. This defines where EventBridge sends the event (to Lambda):\\n1 2 3 4 5 6 7 8 cat \\u0026gt; targets.json \\u0026lt;\\u0026lt; EOF [ { \\u0026#34;Id\\u0026#34;: \\u0026#34;1\\u0026#34;, \\u0026#34;Arn\\u0026#34;: \\u0026#34;$(aws lambda get-function --function-name MakeHealthCheck --query \\u0026#39;Configuration.FunctionArn\\u0026#39; --output text)\\u0026#34; } ] EOF Add target to the rule\\n1 2 3 aws events put-targets \\\\ --rule MakeHealthCheckSchedule \\\\ --targets file://targets.json Updating the Lambda As you change your Python code, redeploy by zipping and updating:\\n1 2 3 4 5 zip -r make-health-check.zip . aws lambda update-function-code \\\\ --function-name MakeHealthCheck \\\\ --zip-file fileb://make-health-check.zip Or use the Makefile…\\nAutomate with Makefile Automate all the manual steps with a Makefile:\\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # Makefile for building and deploying the weather-lambda project .PHONY: install package deploy clean install: pip install -r requirements.txt -t ./src package: cd src \\u0026amp;\\u0026amp; zip -r ../make-health-check.zip . deploy: package aws lambda update-function-code \\\\ --function-name MakeHealthCheck \\\\ --zip-file fileb://make-health-check.zip clean: rm -f make-health-check.zip rm -rf src/__pycache__ Now you can deploy with just:\\n1 make deploy Cleaning Up When you’re done, clean up resources to avoid charges.\\nDelete CloudWatch Event Rule and Targets\\n1 2 3 4 5 6 7 8 # First remove targets from the rule aws events remove-targets \\\\ --rule MakeHealthCheckSchedule \\\\ --ids \\u0026#34;1\\u0026#34; # Then delete the rule itself aws events delete-rule \\\\ --name MakeHealthCheckSchedule Delete lambda function\\n1 2 3 # Delete the function aws lambda delete-function \\\\ --function-name MakeHealthCheck Delete IAM Role and Policies\\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 # First detach any managed policies from the role aws iam detach-role-policy \\\\ --role-name MakeHealthCheckRole \\\\ --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole # Delete any inline policies (if you added any) aws iam list-role-policies --role-name MakeHealthCheckRole --query \\u0026#39;PolicyNames\\u0026#39; --output text | \\\\ while read -r policy; do aws iam delete-role-policy --role-name MakeHealthCheckRole --policy-name \\u0026#34;$policy\\u0026#34; done # Finally, delete the role aws iam delete-role \\\\ --role-name MakeHealthCheckRole Verify Cleanup\\nTo make sure everything is cleaned up:\\n1 2 3 4 5 6 7 8 # Check if function still exists aws lambda get-function --function-name MakeHealthCheck 2\\u0026gt;\\u0026amp;1 || echo \\u0026#34;Function deleted successfully\\u0026#34; # Check if rule still exists aws events describe-rule --name MakeHealthCheckSchedule 2\\u0026gt;\\u0026amp;1 || echo \\u0026#34;Rule deleted successfully\\u0026#34; # Check if role still exists aws iam get-role --role-name MakeHealthCheckRole 2\\u0026gt;\\u0026amp;1 || echo \\u0026#34;Role deleted successfully\\u0026#34; If you\\u0026rsquo;re unsure about any resources, you can use the AWS Console to search for \\u0026ldquo;MakeHealthCheck\\u0026rdquo; across all services to find any remaining resources.\\nOne-liner to find related resources (optional)\\n1 aws resourcegroupstaggingapi get-resources --tag-filters Key=Name,Values=MakeHealthCheck Conclusion: Serverless Scheduling Made Simple By combining AWS Lambda, EventBridge, and Python, you’ve created a lightweight and scalable cron job — without ever worrying about servers, uptime, or instance cost.\\nThis pattern is perfect for:\\nHealth checks and monitoring Scheduled API data ingestion Log cleanup Notifications and alerts With a clean deployment pipeline using a Makefile, and proper IAM practices, your serverless cron architecture is robust, automated, and cloud-native.\\n\"","genre":"\"Cloud\""}</script><meta property="og:image" content="https://citizix.com/og-default.png"><meta name=twitter:card content="summary_large_image"><meta name=twitter:image content="https://citizix.com/og-default.png"><style>.admonition{margin:1.5em 0;padding:0;border-radius:4px;border-inline-start:4px solid;background:var(--blockquote-background-color,#f8f8f8);overflow:hidden}.admonition-title{font-weight:600;padding:.5em 1em;margin:0}.admonition-content{padding:.5em 1em 1em;margin:0}.admonition-content p:last-child{margin-bottom:0}.admonition-tip{border-color:#198754}.admonition-tip .admonition-title{background:rgba(25,135,84,.1);color:#198754}.admonition-note{border-color:#0d6efd}.admonition-note .admonition-title{background:rgba(13,110,253,.1);color:#0d6efd}.admonition-warning{border-color:#ffc107}.admonition-warning .admonition-title{background:rgba(255,193,7,.2);color:#856404}.admonition-danger{border-color:#dc3545}.admonition-danger .admonition-title{background:rgba(220,53,69,.1);color:#dc3545}.admonition-success{border-color:#198754}.admonition-success .admonition-title{background:rgba(25,135,84,.1);color:#198754}[data-scheme=dark] .admonition{background:#373737}[data-scheme=dark] .admonition-warning .admonition-title{color:#ffc107}</style></head><body class=article-page><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KMW4HCHN" height=0 width=0 style=display:none;visibility:hidden></iframe></noscript><script>(function(){const e="StackColorScheme";localStorage.getItem(e)||localStorage.setItem(e,"auto")})()</script><script>(function(){const t="StackColorScheme",e=localStorage.getItem(t),n=window.matchMedia("(prefers-color-scheme: dark)").matches===!0;e=="dark"||e==="auto"&&n?document.documentElement.dataset.scheme="dark":document.documentElement.dataset.scheme="light"})()</script><div class="container main-container flex on-phone--column extended"><aside class="sidebar left-sidebar sticky"><button class="hamburger hamburger--spin" type=button id=toggle-menu aria-label="Toggle Menu">
<span class=hamburger-box><span class=hamburger-inner></span></span></button><header><figure class=site-avatar><a href=/><img src=/avatar.png width=528 height=560 class=site-logo loading=lazy alt=Avatar>
</a><span class=emoji>🍥</span></figure><div class=site-meta><h1 class=site-name><a href=/>Citizix, The Best blog for Linux, Opensource, Devops, Cloud and all things awesome tech.</a></h1><h2 class=site-description>Devops, Cloud, Infrastructure and Tech Content.</h2></div></header><ol class=menu-social><li><a href=https://github.com/citizix title=GitHub rel=me><svg class="icon icon-tabler icon-tabler-brand-github" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 19c-4.3 1.4-4.3-2.5-6-3m12 5v-3.5c0-1 .1-1.4-.5-2 2.8-.3 5.5-1.4 5.5-6a4.6 4.6.0 00-1.3-3.2 4.2 4.2.0 00-.1-3.2s-1.1-.3-3.5 1.3a12.3 12.3.0 00-6.2.0C6.5 2.8 5.4 3.1 5.4 3.1a4.2 4.2.0 00-.1 3.2A4.6 4.6.0 004 9.5c0 4.6 2.7 5.7 5.5 6-.6.6-.6 1.2-.5 2V21"/></svg></a></li><li><a href=https://twitter.com/citizixdotcom title=Twitter rel=me><svg class="icon icon-tabler icon-tabler-brand-twitter" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M22 4.01c-1 .49-1.98.689-3 .99-1.121-1.265-2.783-1.335-4.38-.737S11.977 6.323 12 8v1c-3.245.083-6.135-1.395-8-4 0 0-4.182 7.433 4 11-1.872 1.247-3.739 2.088-6 2 3.308 1.803 6.913 2.423 10.034 1.517 3.58-1.04 6.522-3.723 7.651-7.742a13.84 13.84.0 00.497-3.753C20.18 7.773 21.692 5.25 22 4.009z"/></svg></a></li></ol><ol class=menu id=main-menu><li><a href=/><svg class="icon icon-tabler icon-tabler-home" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><polyline points="5 12 3 12 12 3 21 12 19 12"/><path d="M5 12v7a2 2 0 002 2h10a2 2 0 002-2v-7"/><path d="M9 21v-6a2 2 0 012-2h2a2 2 0 012 2v6"/></svg>
<span>Home</span></a></li><li><a href=/search/><svg class="icon icon-tabler icon-tabler-search" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="10" cy="10" r="7"/><line x1="21" y1="21" x2="15" y2="15"/></svg>
<span>Search - Citizix</span></a></li><li><a href=/about-us/><svg class="icon icon-tabler icon-tabler-user" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="7" r="4"/><path d="M6 21v-2a4 4 0 014-4h4a4 4 0 014 4v2"/></svg>
<span>About Us</span></a></li><li><a href=/contact-us/><svg class="icon icon-tabler icon-tabler-hash" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><line x1="5" y1="9" x2="19" y2="9"/><line x1="5" y1="15" x2="19" y2="15"/><line x1="11" y1="4" x2="7" y2="20"/><line x1="17" y1="4" x2="13" y2="20"/></svg>
<span>Contact Us - Citizix</span></a></li><li><a href=/privacy-policy/><svg class="icon icon-tabler icon-tabler-infinity" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><path d="M9.828 9.172a4 4 0 100 5.656A10 10 0 0012 12a10 10 0 012.172-2.828 4 4 0 110 5.656A10 10 0 0112 12 10 10 0 009.828 9.172"/></svg>
<span>Privacy Policy - Citizix</span></a></li><li class=menu-bottom-section><ol class=menu><li id=dark-mode-toggle><svg class="icon icon-tabler icon-tabler-toggle-left" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="8" cy="12" r="2"/><rect x="2" y="6" width="20" height="12" rx="6"/></svg>
<svg class="icon icon-tabler icon-tabler-toggle-right" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="16" cy="12" r="2"/><rect x="2" y="6" width="20" height="12" rx="6"/></svg>
<span>Dark Mode</span></li></ol></li></ol></aside><aside class="sidebar right-sidebar sticky"><section class="widget archives"><div class=widget-icon><svg class="icon icon-tabler icon-tabler-hash" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><line x1="5" y1="9" x2="19" y2="9"/><line x1="5" y1="15" x2="19" y2="15"/><line x1="11" y1="4" x2="7" y2="20"/><line x1="17" y1="4" x2="13" y2="20"/></svg></div><h2 class="widget-title section-title">Table of contents</h2><div class=widget--toc><nav class=toc-nav id=TableOfContents><ol><li><a href=#the-code-logic>The Code Logic</a><ol><li><a href=#lambda-entry-point>Lambda Entry Point</a></li></ol></li><li><a href=#packaging-the-code>Packaging the Code</a></li><li><a href=#creating-iam-role-for-lambda>Creating IAM Role for Lambda</a></li><li><a href=#deploying-the-lambda-function>Deploying the Lambda Function</a></li><li><a href=#setting-up-a-cron-with-eventbridge>Setting Up a Cron with EventBridge</a><ol><li><a href=#give-eventbridge-permission-to-trigger-lambda>Give EventBridge Permission to Trigger Lambda</a></li></ol></li><li><a href=#create-target>Create Target</a></li><li><a href=#updating-the-lambda>Updating the Lambda</a></li><li><a href=#automate-with-makefile>Automate with Makefile</a></li><li><a href=#cleaning-up>Cleaning Up</a></li><li><a href=#conclusion-serverless-scheduling-made-simple>Conclusion: Serverless Scheduling Made Simple</a></li></ol></nav></div></section></aside><main class="main full-width"><article class=main-article><header class=article-header><div class=article-details><header class=article-category><a href=/categories/cloud/ style=background-color:#bed3ef;color:#0f233d>Cloud
</a><a href=/categories/aws/ style=background-color:#d3efbe;color:#233d0f>AWS</a></header><div class=article-title-wrapper><h2 class=article-title><a href=/how-to-setup-and-run-aws-lambda-as-crons-with-eventsbridge.md>How to Setup and Run Crons With Lambda in Aws and Eventsbridge</a></h2><h3 class=article-subtitle>Step-by-step guide on How to Setup and Run Crons With Labda in Aws and Eventsbridge</h3></div><footer class=article-meta><div class=inline-meta><svg class="icon icon-tabler icon-tabler-calendar-time" width="56" height="56" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><path d="M11.795 21H5a2 2 0 01-2-2V7a2 2 0 012-2h12a2 2 0 012 2v4"/><circle cx="18" cy="18" r="4"/><path d="M15 3v4"/><path d="M7 3v4"/><path d="M3 11h16"/><path d="M18 16.496V18l1 1"/></svg>
<time class=article-time--published datetime=2025-04-01T15:46:25+03:00>Apr 01, 2025</time>
<svg class="icon icon-tabler icon-tabler-clock" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 15"/></svg>
<time class=article-time--reading>6 minutes read</time></div></footer></div></header><aside class=article-toc><details><summary><div class=article-toc-title><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chevron-right"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 6l6 6-6 6"/></svg>
<span>Table of contents</span></div></summary><nav class=toc-nav><ol><li><a href=#the-code-logic>The Code Logic</a><ol><li><a href=#lambda-entry-point>Lambda Entry Point</a></li></ol></li><li><a href=#packaging-the-code>Packaging the Code</a></li><li><a href=#creating-iam-role-for-lambda>Creating IAM Role for Lambda</a></li><li><a href=#deploying-the-lambda-function>Deploying the Lambda Function</a></li><li><a href=#setting-up-a-cron-with-eventbridge>Setting Up a Cron with EventBridge</a><ol><li><a href=#give-eventbridge-permission-to-trigger-lambda>Give EventBridge Permission to Trigger Lambda</a></li></ol></li><li><a href=#create-target>Create Target</a></li><li><a href=#updating-the-lambda>Updating the Lambda</a></li><li><a href=#automate-with-makefile>Automate with Makefile</a></li><li><a href=#cleaning-up>Cleaning Up</a></li><li><a href=#conclusion-serverless-scheduling-made-simple>Conclusion: Serverless Scheduling Made Simple</a></li></ol></nav></details></aside><section class=article-content><p>Automation is at the heart of reliable cloud systems. Whether you want to fetch weather data, clean logs, update caches, or ping a health endpoint, scheduled tasks (aka cron jobs) are essential.</p><p>Traditionally, cron jobs lived on servers. But in the cloud-native world, we aim to make our tasks serverless, secure, and scalable. Enter:</p><ul><li>AWS Lambda — for running lightweight, event-driven functions.</li><li>Amazon EventBridge (formerly CloudWatch Events) — for triggering those functions on a schedule (like crontab).</li></ul><p>In this guide, we’ll explore how to:</p><ul><li>Package a Python script for AWS Lambda</li><li>Run it every 6 hours using EventBridge</li><li>Automate deployment with a Makefile</li><li>Clean up all resources when you’re done</li></ul><p>Let’s dive in.</p><h2 id=the-code-logic>The Code Logic</h2><p>Let’s say we have a Python script that:</p><ul><li>Fetches weather data from WeatherAPI</li><li>Sends that data to a debug API endpoint for processing or logging</li></ul><p>Here’s our logic saved in <code>src/script.py</code>:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt> 1
</span><span class=lnt> 2
</span><span class=lnt> 3
</span><span class=lnt> 4
</span><span class=lnt> 5
</span><span class=lnt> 6
</span><span class=lnt> 7
</span><span class=lnt> 8
</span><span class=lnt> 9
</span><span class=lnt>10
</span><span class=lnt>11
</span><span class=lnt>12
</span><span class=lnt>13
</span><span class=lnt>14
</span><span class=lnt>15
</span><span class=lnt>16
</span><span class=lnt>17
</span><span class=lnt>18
</span><span class=lnt>19
</span><span class=lnt>20
</span><span class=lnt>21
</span><span class=lnt>22
</span><span class=lnt>23
</span><span class=lnt>24
</span><span class=lnt>25
</span><span class=lnt>26
</span><span class=lnt>27
</span><span class=lnt>28
</span><span class=lnt>29
</span><span class=lnt>30
</span><span class=lnt>31
</span><span class=lnt>32
</span><span class=lnt>33
</span><span class=lnt>34
</span><span class=lnt>35
</span><span class=lnt>36
</span><span class=lnt>37
</span><span class=lnt>38
</span><span class=lnt>39
</span><span class=lnt>40
</span><span class=lnt>41
</span><span class=lnt>42
</span><span class=lnt>43
</span><span class=lnt>44
</span><span class=lnt>45
</span><span class=lnt>46
</span><span class=lnt>47
</span><span class=lnt>48
</span><span class=lnt>49
</span><span class=lnt>50
</span><span class=lnt>51
</span><span class=lnt>52
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-py data-lang=py><span class=line><span class=cl><span class=kn>import</span> <span class=nn>json</span>
</span></span><span class=line><span class=cl><span class=kn>import</span> <span class=nn>os</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=kn>import</span> <span class=nn>requests</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=k>def</span> <span class=nf>get_weather_data</span><span class=p>(</span><span class=n>city</span><span class=o>=</span><span class=s2>&#34;Nairobi&#34;</span><span class=p>):</span>
</span></span><span class=line><span class=cl>    <span class=n>api_key</span> <span class=o>=</span> <span class=n>os</span><span class=o>.</span><span class=n>environ</span><span class=o>.</span><span class=n>get</span><span class=p>(</span><span class=s2>&#34;WEATHERAPI_KEY&#34;</span><span class=p>,</span> <span class=s2>&#34;e35b01c9046641c2af095849252503&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>    <span class=n>url</span> <span class=o>=</span> <span class=sa>f</span><span class=s2>&#34;http://api.weatherapi.com/v1/current.json?key=</span><span class=si>{</span><span class=n>api_key</span><span class=si>}</span><span class=s2>&amp;q=</span><span class=si>{</span><span class=n>city</span><span class=si>}</span><span class=s2>&#34;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl>    <span class=k>try</span><span class=p>:</span>
</span></span><span class=line><span class=cl>        <span class=n>response</span> <span class=o>=</span> <span class=n>requests</span><span class=o>.</span><span class=n>get</span><span class=p>(</span><span class=n>url</span><span class=p>)</span>
</span></span><span class=line><span class=cl>        <span class=n>response</span><span class=o>.</span><span class=n>raise_for_status</span><span class=p>()</span>
</span></span><span class=line><span class=cl>        <span class=k>return</span> <span class=n>response</span><span class=o>.</span><span class=n>json</span><span class=p>()</span>
</span></span><span class=line><span class=cl>    <span class=k>except</span> <span class=n>requests</span><span class=o>.</span><span class=n>exceptions</span><span class=o>.</span><span class=n>RequestException</span> <span class=k>as</span> <span class=n>e</span><span class=p>:</span>
</span></span><span class=line><span class=cl>        <span class=nb>print</span><span class=p>(</span><span class=sa>f</span><span class=s2>&#34;Error fetching weather data: </span><span class=si>{</span><span class=n>e</span><span class=si>}</span><span class=s2>&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>        <span class=k>return</span> <span class=kc>None</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=k>def</span> <span class=nf>send_to_jsonplaceholder</span><span class=p>(</span><span class=n>data</span><span class=p>):</span>
</span></span><span class=line><span class=cl>    <span class=n>url</span> <span class=o>=</span> <span class=s2>&#34;https://stage-opsman-api.citizix.com/debug-request&#34;</span>
</span></span><span class=line><span class=cl>    <span class=n>payload</span> <span class=o>=</span> <span class=p>{</span>
</span></span><span class=line><span class=cl>        <span class=s2>&#34;title&#34;</span><span class=p>:</span> <span class=sa>f</span><span class=s2>&#34;Weather Report for </span><span class=si>{</span><span class=n>data</span><span class=p>[</span><span class=s1>&#39;location&#39;</span><span class=p>][</span><span class=s1>&#39;name&#39;</span><span class=p>]</span><span class=si>}</span><span class=s2>&#34;</span><span class=p>,</span>
</span></span><span class=line><span class=cl>        <span class=s2>&#34;body&#34;</span><span class=p>:</span> <span class=sa>f</span><span class=s2>&#34;Temperature: </span><span class=si>{</span><span class=n>data</span><span class=p>[</span><span class=s1>&#39;current&#39;</span><span class=p>][</span><span class=s1>&#39;temp_c&#39;</span><span class=p>]</span><span class=si>}</span><span class=s2>°C, Conditions: </span><span class=si>{</span><span class=n>data</span><span class=p>[</span><span class=s1>&#39;current&#39;</span><span class=p>][</span><span class=s1>&#39;condition&#39;</span><span class=p>][</span><span class=s1>&#39;text&#39;</span><span class=p>]</span><span class=si>}</span><span class=s2>, Humidity: </span><span class=si>{</span><span class=n>data</span><span class=p>[</span><span class=s1>&#39;current&#39;</span><span class=p>][</span><span class=s1>&#39;humidity&#39;</span><span class=p>]</span><span class=si>}</span><span class=s2>%&#34;</span><span class=p>,</span>
</span></span><span class=line><span class=cl>        <span class=s2>&#34;userId&#34;</span><span class=p>:</span> <span class=mi>1</span>
</span></span><span class=line><span class=cl>    <span class=p>}</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl>    <span class=k>try</span><span class=p>:</span>
</span></span><span class=line><span class=cl>        <span class=n>response</span> <span class=o>=</span> <span class=n>requests</span><span class=o>.</span><span class=n>post</span><span class=p>(</span><span class=n>url</span><span class=p>,</span> <span class=n>json</span><span class=o>=</span><span class=n>payload</span><span class=p>)</span>
</span></span><span class=line><span class=cl>        <span class=n>response</span><span class=o>.</span><span class=n>raise_for_status</span><span class=p>()</span>
</span></span><span class=line><span class=cl>        <span class=k>return</span> <span class=n>response</span><span class=o>.</span><span class=n>json</span><span class=p>()</span>
</span></span><span class=line><span class=cl>    <span class=k>except</span> <span class=n>requests</span><span class=o>.</span><span class=n>exceptions</span><span class=o>.</span><span class=n>RequestException</span> <span class=k>as</span> <span class=n>e</span><span class=p>:</span>
</span></span><span class=line><span class=cl>        <span class=nb>print</span><span class=p>(</span><span class=sa>f</span><span class=s2>&#34;Error sending data: </span><span class=si>{</span><span class=n>e</span><span class=si>}</span><span class=s2>&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>        <span class=k>return</span> <span class=kc>None</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=k>def</span> <span class=nf>main</span><span class=p>():</span>
</span></span><span class=line><span class=cl>    <span class=n>city</span> <span class=o>=</span> <span class=n>os</span><span class=o>.</span><span class=n>environ</span><span class=o>.</span><span class=n>get</span><span class=p>(</span><span class=s2>&#34;WEATHER_CITY&#34;</span><span class=p>,</span> <span class=s2>&#34;Nairobi&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>    <span class=n>weather_data</span> <span class=o>=</span> <span class=n>get_weather_data</span><span class=p>(</span><span class=n>city</span><span class=p>)</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl>    <span class=k>if</span> <span class=n>weather_data</span><span class=p>:</span>
</span></span><span class=line><span class=cl>        <span class=nb>print</span><span class=p>(</span><span class=sa>f</span><span class=s2>&#34;Successfully retrieved weather data for </span><span class=si>{</span><span class=n>city</span><span class=si>}</span><span class=s2>&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>        <span class=n>result</span> <span class=o>=</span> <span class=n>send_to_jsonplaceholder</span><span class=p>(</span><span class=n>weather_data</span><span class=p>)</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl>        <span class=k>if</span> <span class=n>result</span><span class=p>:</span>
</span></span><span class=line><span class=cl>            <span class=nb>print</span><span class=p>(</span><span class=sa>f</span><span class=s2>&#34;Successfully sent data to JSONPlaceholder API&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>            <span class=nb>print</span><span class=p>(</span><span class=sa>f</span><span class=s2>&#34;Response: </span><span class=si>{</span><span class=n>json</span><span class=o>.</span><span class=n>dumps</span><span class=p>(</span><span class=n>result</span><span class=p>,</span> <span class=n>indent</span><span class=o>=</span><span class=mi>2</span><span class=p>)</span><span class=si>}</span><span class=s2>&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>        <span class=k>else</span><span class=p>:</span>
</span></span><span class=line><span class=cl>            <span class=nb>print</span><span class=p>(</span><span class=s2>&#34;Failed to send data to JSONPlaceholder API&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>    <span class=k>else</span><span class=p>:</span>
</span></span><span class=line><span class=cl>        <span class=nb>print</span><span class=p>(</span><span class=sa>f</span><span class=s2>&#34;Failed to retrieve weather data for </span><span class=si>{</span><span class=n>city</span><span class=si>}</span><span class=s2>&#34;</span><span class=p>)</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=k>if</span> <span class=vm>__name__</span> <span class=o>==</span> <span class=s2>&#34;__main__&#34;</span><span class=p>:</span>
</span></span><span class=line><span class=cl>    <span class=n>main</span><span class=p>()</span>
</span></span></code></pre></td></tr></table></div></div><h3 id=lambda-entry-point>Lambda Entry Point</h3><p>We wrap this in a Lambda-compatible handler in <code>src/main.py</code>:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span><span class=lnt>4
</span><span class=lnt>5
</span><span class=lnt>6
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-py data-lang=py><span class=line><span class=cl><span class=kn>from</span> <span class=nn>script</span> <span class=kn>import</span> <span class=n>main</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=k>def</span> <span class=nf>handler</span><span class=p>(</span><span class=n>event</span><span class=p>,</span> <span class=n>context</span><span class=p>):</span>
</span></span><span class=line><span class=cl>    <span class=n>main</span><span class=p>()</span>
</span></span><span class=line><span class=cl>    <span class=k>return</span> <span class=p>{</span><span class=s1>&#39;statusCode&#39;</span><span class=p>:</span> <span class=mi>200</span><span class=p>}</span>
</span></span></code></pre></td></tr></table></div></div><p>This is the file AWS Lambda will call when the function is triggered.</p><h2 id=packaging-the-code>Packaging the Code</h2><p>To make Lambda understand your code:</p><ul><li>Add dependencies in <code>requirements.txt</code>:</li></ul><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>requests
</span></span></code></pre></td></tr></table></div></div><ul><li>Install them locally into <code>src/</code>:</li></ul><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>pip install -r requirements.txt -t ./src
</span></span></code></pre></td></tr></table></div></div><ul><li>Package the folder:</li></ul><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl><span class=nb>cd</span> src <span class=o>&amp;&amp;</span> zip -r ../make-health-check.zip .
</span></span></code></pre></td></tr></table></div></div><p>This ZIP will be uploaded to AWS as your Lambda function code.</p><h2 id=creating-iam-role-for-lambda>Creating IAM Role for Lambda</h2><p>AWS Lambda needs permissions to run. So, we create a role and attach basic execution permissions:</p><ul><li>Trust policy</li></ul><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt> 1
</span><span class=lnt> 2
</span><span class=lnt> 3
</span><span class=lnt> 4
</span><span class=lnt> 5
</span><span class=lnt> 6
</span><span class=lnt> 7
</span><span class=lnt> 8
</span><span class=lnt> 9
</span><span class=lnt>10
</span><span class=lnt>11
</span><span class=lnt>12
</span><span class=lnt>13
</span><span class=lnt>14
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>cat &gt; trust-policy.json <span class=s>&lt;&lt; EOF
</span></span></span><span class=line><span class=cl><span class=s>{
</span></span></span><span class=line><span class=cl><span class=s>  &#34;Version&#34;: &#34;2012-10-17&#34;,
</span></span></span><span class=line><span class=cl><span class=s>  &#34;Statement&#34;: [
</span></span></span><span class=line><span class=cl><span class=s>    {
</span></span></span><span class=line><span class=cl><span class=s>      &#34;Effect&#34;: &#34;Allow&#34;,
</span></span></span><span class=line><span class=cl><span class=s>      &#34;Principal&#34;: {
</span></span></span><span class=line><span class=cl><span class=s>        &#34;Service&#34;: &#34;lambda.amazonaws.com&#34;
</span></span></span><span class=line><span class=cl><span class=s>      },
</span></span></span><span class=line><span class=cl><span class=s>      &#34;Action&#34;: &#34;sts:AssumeRole&#34;
</span></span></span><span class=line><span class=cl><span class=s>    }
</span></span></span><span class=line><span class=cl><span class=s>  ]
</span></span></span><span class=line><span class=cl><span class=s>}
</span></span></span><span class=line><span class=cl><span class=s>EOF</span>
</span></span></code></pre></td></tr></table></div></div><p>Create Iam role</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>aws iam create-role --role-name MakeHealthCheckRole --assume-role-policy-document file://trust-policy.json
</span></span></code></pre></td></tr></table></div></div><p>Attach basic execution policy</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>aws iam attach-role-policy --role-name MakeHealthCheckRole --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
</span></span></code></pre></td></tr></table></div></div><p>Get role arn</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>aws iam get-role --role-name MakeHealthCheckRole --query <span class=s1>&#39;Role.Arn&#39;</span> --output text
</span></span></code></pre></td></tr></table></div></div><h2 id=deploying-the-lambda-function>Deploying the Lambda Function</h2><p>Use the zipped code to create the Lambda function:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span><span class=lnt>4
</span><span class=lnt>5
</span><span class=lnt>6
</span><span class=lnt>7
</span><span class=lnt>8
</span><span class=lnt>9
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>zip -r make-monitor.zip .
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl>aws lambda create-function <span class=se>\
</span></span></span><span class=line><span class=cl>  --function-name MakeHealthCheck <span class=se>\
</span></span></span><span class=line><span class=cl>  --zip-file fileb://make-monitor.zip <span class=se>\
</span></span></span><span class=line><span class=cl>  --handler main.handler <span class=se>\
</span></span></span><span class=line><span class=cl>  --runtime python3.12 <span class=se>\
</span></span></span><span class=line><span class=cl>  --role arn:aws:iam::&lt;your-account-id&gt;:role/MakeHealthCheckRole <span class=se>\
</span></span></span><span class=line><span class=cl>  --timeout <span class=m>30</span>
</span></span></code></pre></td></tr></table></div></div><p>Make sure to replace <code>&lt;your-account-id></code> with your real AWS account number.</p><h2 id=setting-up-a-cron-with-eventbridge>Setting Up a Cron with EventBridge</h2><p>AWS EventBridge allows us to run the Lambda every 6 hours using a cron expression:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>aws events put-rule <span class=se>\
</span></span></span><span class=line><span class=cl>  --name MakeHealthCheckSchedule <span class=se>\
</span></span></span><span class=line><span class=cl>  --schedule-expression <span class=s2>&#34;cron(0 0/6 * * ? *)&#34;</span>
</span></span></code></pre></td></tr></table></div></div><p>This runs the function at 00:00, 06:00, 12:00, and 18:00 UTC daily.</p><h3 id=give-eventbridge-permission-to-trigger-lambda>Give EventBridge Permission to Trigger Lambda</h3><p>Add permission for CloudWatch to invoke Lambda</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span><span class=lnt>4
</span><span class=lnt>5
</span><span class=lnt>6
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>aws lambda add-permission <span class=se>\
</span></span></span><span class=line><span class=cl>  --function-name MakeHealthCheck <span class=se>\
</span></span></span><span class=line><span class=cl>  --statement-id MakeHealthCheckSchedule <span class=se>\
</span></span></span><span class=line><span class=cl>  --action lambda:InvokeFunction <span class=se>\
</span></span></span><span class=line><span class=cl>  --principal events.amazonaws.com <span class=se>\
</span></span></span><span class=line><span class=cl>  --source-arn <span class=k>$(</span>aws events describe-rule --name MakeHealthCheckSchedule --query <span class=s1>&#39;Arn&#39;</span> --output text<span class=k>)</span>
</span></span></code></pre></td></tr></table></div></div><h2 id=create-target>Create Target</h2><p>Create target JSON file. This defines where EventBridge sends the event (to Lambda):</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span><span class=lnt>4
</span><span class=lnt>5
</span><span class=lnt>6
</span><span class=lnt>7
</span><span class=lnt>8
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>cat &gt; targets.json <span class=s>&lt;&lt; EOF
</span></span></span><span class=line><span class=cl><span class=s>[
</span></span></span><span class=line><span class=cl><span class=s>  {
</span></span></span><span class=line><span class=cl><span class=s>    &#34;Id&#34;: &#34;1&#34;,
</span></span></span><span class=line><span class=cl><span class=s>    &#34;Arn&#34;: &#34;$(aws lambda get-function --function-name MakeHealthCheck --query &#39;Configuration.FunctionArn&#39; --output text)&#34;
</span></span></span><span class=line><span class=cl><span class=s>  }
</span></span></span><span class=line><span class=cl><span class=s>]
</span></span></span><span class=line><span class=cl><span class=s>EOF</span>
</span></span></code></pre></td></tr></table></div></div><p>Add target to the rule</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>aws events put-targets <span class=se>\
</span></span></span><span class=line><span class=cl>  --rule MakeHealthCheckSchedule <span class=se>\
</span></span></span><span class=line><span class=cl>  --targets file://targets.json
</span></span></code></pre></td></tr></table></div></div><h2 id=updating-the-lambda>Updating the Lambda</h2><p>As you change your Python code, redeploy by zipping and updating:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span><span class=lnt>4
</span><span class=lnt>5
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>zip -r make-health-check.zip .
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl>aws lambda update-function-code <span class=se>\
</span></span></span><span class=line><span class=cl>  --function-name MakeHealthCheck <span class=se>\
</span></span></span><span class=line><span class=cl>  --zip-file fileb://make-health-check.zip
</span></span></code></pre></td></tr></table></div></div><p>Or use the Makefile…</p><h2 id=automate-with-makefile>Automate with Makefile</h2><p>Automate all the manual steps with a Makefile:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt> 1
</span><span class=lnt> 2
</span><span class=lnt> 3
</span><span class=lnt> 4
</span><span class=lnt> 5
</span><span class=lnt> 6
</span><span class=lnt> 7
</span><span class=lnt> 8
</span><span class=lnt> 9
</span><span class=lnt>10
</span><span class=lnt>11
</span><span class=lnt>12
</span><span class=lnt>13
</span><span class=lnt>14
</span><span class=lnt>15
</span><span class=lnt>16
</span><span class=lnt>17
</span><span class=lnt>18
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-Makefile data-lang=Makefile><span class=line><span class=cl><span class=c># Makefile for building and deploying the weather-lambda project
</span></span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=nf>.PHONY</span><span class=o>:</span> <span class=n>install</span> <span class=n>package</span> <span class=n>deploy</span> <span class=n>clean</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=nf>install</span><span class=o>:</span>
</span></span><span class=line><span class=cl> pip install -r requirements.txt -t ./src
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=nf>package</span><span class=o>:</span>
</span></span><span class=line><span class=cl> <span class=nb>cd</span> src <span class=o>&amp;&amp;</span> zip -r ../make-health-check.zip .
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=nf>deploy</span><span class=o>:</span> <span class=n>package</span>
</span></span><span class=line><span class=cl> aws lambda update-function-code <span class=se>\
</span></span></span><span class=line><span class=cl>  --function-name MakeHealthCheck <span class=se>\
</span></span></span><span class=line><span class=cl>  --zip-file fileb://make-health-check.zip
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=nf>clean</span><span class=o>:</span>
</span></span><span class=line><span class=cl> rm -f make-health-check.zip
</span></span><span class=line><span class=cl> rm -rf src/__pycache__
</span></span></code></pre></td></tr></table></div></div><p>Now you can deploy with just:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>make deploy
</span></span></code></pre></td></tr></table></div></div><h2 id=cleaning-up>Cleaning Up</h2><p>When you’re done, clean up resources to avoid charges.</p><p>Delete CloudWatch Event Rule and Targets</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span><span class=lnt>4
</span><span class=lnt>5
</span><span class=lnt>6
</span><span class=lnt>7
</span><span class=lnt>8
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl><span class=c1># First remove targets from the rule</span>
</span></span><span class=line><span class=cl>aws events remove-targets <span class=se>\
</span></span></span><span class=line><span class=cl>  --rule MakeHealthCheckSchedule <span class=se>\
</span></span></span><span class=line><span class=cl>  --ids <span class=s2>&#34;1&#34;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1># Then delete the rule itself</span>
</span></span><span class=line><span class=cl>aws events delete-rule <span class=se>\
</span></span></span><span class=line><span class=cl>  --name MakeHealthCheckSchedule
</span></span></code></pre></td></tr></table></div></div><p>Delete lambda function</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl><span class=c1># Delete the function</span>
</span></span><span class=line><span class=cl>aws lambda delete-function <span class=se>\
</span></span></span><span class=line><span class=cl>  --function-name MakeHealthCheck
</span></span></code></pre></td></tr></table></div></div><p>Delete IAM Role and Policies</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt> 1
</span><span class=lnt> 2
</span><span class=lnt> 3
</span><span class=lnt> 4
</span><span class=lnt> 5
</span><span class=lnt> 6
</span><span class=lnt> 7
</span><span class=lnt> 8
</span><span class=lnt> 9
</span><span class=lnt>10
</span><span class=lnt>11
</span><span class=lnt>12
</span><span class=lnt>13
</span><span class=lnt>14
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl><span class=c1># First detach any managed policies from the role</span>
</span></span><span class=line><span class=cl>aws iam detach-role-policy <span class=se>\
</span></span></span><span class=line><span class=cl>  --role-name MakeHealthCheckRole <span class=se>\
</span></span></span><span class=line><span class=cl>  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1># Delete any inline policies (if you added any)</span>
</span></span><span class=line><span class=cl>aws iam list-role-policies --role-name MakeHealthCheckRole --query <span class=s1>&#39;PolicyNames&#39;</span> --output text <span class=p>|</span> <span class=se>\
</span></span></span><span class=line><span class=cl><span class=k>while</span> <span class=nb>read</span> -r policy<span class=p>;</span> <span class=k>do</span>
</span></span><span class=line><span class=cl>  aws iam delete-role-policy --role-name MakeHealthCheckRole --policy-name <span class=s2>&#34;</span><span class=nv>$policy</span><span class=s2>&#34;</span>
</span></span><span class=line><span class=cl><span class=k>done</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1># Finally, delete the role</span>
</span></span><span class=line><span class=cl>aws iam delete-role <span class=se>\
</span></span></span><span class=line><span class=cl>  --role-name MakeHealthCheckRole
</span></span></code></pre></td></tr></table></div></div><p>Verify Cleanup</p><p>To make sure everything is cleaned up:</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span><span class=lnt>2
</span><span class=lnt>3
</span><span class=lnt>4
</span><span class=lnt>5
</span><span class=lnt>6
</span><span class=lnt>7
</span><span class=lnt>8
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl><span class=c1># Check if function still exists</span>
</span></span><span class=line><span class=cl>aws lambda get-function --function-name MakeHealthCheck 2&gt;<span class=p>&amp;</span><span class=m>1</span> <span class=o>||</span> <span class=nb>echo</span> <span class=s2>&#34;Function deleted successfully&#34;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1># Check if rule still exists</span>
</span></span><span class=line><span class=cl>aws events describe-rule --name MakeHealthCheckSchedule 2&gt;<span class=p>&amp;</span><span class=m>1</span> <span class=o>||</span> <span class=nb>echo</span> <span class=s2>&#34;Rule deleted successfully&#34;</span>
</span></span><span class=line><span class=cl>
</span></span><span class=line><span class=cl><span class=c1># Check if role still exists</span>
</span></span><span class=line><span class=cl>aws iam get-role --role-name MakeHealthCheckRole 2&gt;<span class=p>&amp;</span><span class=m>1</span> <span class=o>||</span> <span class=nb>echo</span> <span class=s2>&#34;Role deleted successfully&#34;</span>
</span></span></code></pre></td></tr></table></div></div><p>If you&rsquo;re unsure about any resources, you can use the AWS Console to search for &ldquo;MakeHealthCheck&rdquo; across all services to find any remaining resources.</p><p>One-liner to find related resources (optional)</p><div class=highlight><div class=chroma><table class=lntable><tr><td class=lntd><pre tabindex=0 class=chroma><code><span class=lnt>1
</span></code></pre></td><td class=lntd><pre tabindex=0 class=chroma><code class=language-sh data-lang=sh><span class=line><span class=cl>aws resourcegroupstaggingapi get-resources --tag-filters <span class=nv>Key</span><span class=o>=</span>Name,Values<span class=o>=</span>MakeHealthCheck
</span></span></code></pre></td></tr></table></div></div><h2 id=conclusion-serverless-scheduling-made-simple>Conclusion: Serverless Scheduling Made Simple</h2><p>By combining AWS Lambda, EventBridge, and Python, you’ve created a lightweight and scalable cron job — without ever worrying about servers, uptime, or instance cost.</p><p>This pattern is perfect for:</p><ul><li>Health checks and monitoring</li><li>Scheduled API data ingestion</li><li>Log cleanup</li><li>Notifications and alerts</li></ul><p>With a clean deployment pipeline using a Makefile, and proper IAM practices, your serverless cron architecture is robust, automated, and cloud-native.</p></section><footer class="article-meta article-footer"><section class=article-tags><a href=/tags/lambda/>Lambda</a>
<a href=/tags/aws/>Aws</a>
<a href=/tags/eventsbridge/>Eventsbridge</a>
<a href=/tags/automations/>Automations</a></section><section class="article-lastmod inline-meta"><svg class="icon icon-tabler icon-tabler-clock" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z"/><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 15"/></svg>
<span>Last updated on Jun 06, 2026 22:48 +0300</span></section></footer></article><aside><h2 class=section-title>Related content</h2><div class=subsection-list><div class=article-list--tile><article><a href=/how-to-run-aws-lambda-as-cron-in-aws-iac-with-terraform/><div class=article-details><h2 class=article-title>How to Run AWS lambda as cron in AWS - IaC with terraform</h2></div></a></article><article><a href=/how-to-export-amazon-eks-logs-to-cloudwatch-using-fluent-bit/><div class=article-details><h2 class=article-title>How to Export Amazon EKS Logs to CloudWatch Using Fluent Bit</h2></div></a></article><article><a href=/complete-guide-to-setting-up-autoscaling-with-karpenter-on-amazon-eks/><div class=article-details><h2 class=article-title>Complete Guide to Setting Up Autoscaling with Karpenter on Amazon EKS</h2></div></a></article><article><a href=/how-to-set-up-minio-in-ubuntu-or-debian-using-ansible/><div class=article-details><h2 class=article-title>Automating MinIO Installation on Ubuntu or Debian Using Ansible</h2></div></a></article><article><a href=/how-to-set-up-cloudfront-to-serve-static-content-using-terraform/><div class=article-details><h2 class=article-title>How to Set Up Cloudfront to Serve Static Content</h2></div></a></article></div></div></aside><div class=disqus-container><div id=disqus_thread></div><script>window.disqus_config=function(){},function(){if(["localhost","127.0.0.1"].indexOf(window.location.hostname)!=-1){document.getElementById("disqus_thread").innerHTML="Disqus comments not available by default when the website is previewed locally.";return}var t=document,e=t.createElement("script");e.async=!0,e.src="//citizix.disqus.com/embed.js",e.setAttribute("data-timestamp",+new Date),(t.head||t.body).appendChild(e)}()</script><noscript>Please enable JavaScript to view the <a href=https://disqus.com/?ref_noscript>comments powered by Disqus.</a></noscript><a href=https://disqus.com class=dsq-brlink>comments powered by <span class=logo-disqus>Disqus</span></a></div><style>.disqus-container{background-color:var(--card-background);border-radius:var(--card-border-radius);box-shadow:var(--shadow-l1);padding:var(--card-padding)}</style><script>window.addEventListener("onColorSchemeChange",e=>{typeof DISQUS=="object"&&DISQUS.reset({reload:!0})})</script><footer class=site-footer><section class=copyright>&copy;
2020 -
2026 Citizix, Ltd.</section><section class=powerby>Citizix Ltd<br>Built with <a href=https://gohugo.io/ target=_blank rel=noopener>Hugo</a><br>Theme <b><a href=https://github.com/CaiJimmy/hugo-theme-stack target=_blank rel=noopener data-version=4.0.0>Stack</a></b> designed by <a href=https://jimmycai.com target=_blank rel=noopener>Jimmy</a></section></footer><script type=module>
    import gallery from '\/ts\/gallery.js';

    const articleContent = document.querySelector('.article-content');
    const shouldLoad = articleContent && (articleContent.querySelectorAll('figure').length > 0 || articleContent.querySelectorAll('img.gallery-image').length > 0);

    if (shouldLoad) {
        gallery(articleContent);

        const PhotoSwipeLightbox = (await import("https:\/\/cdn.jsdelivr.net\/npm\/photoswipe@5.4.4\/dist\/photoswipe-lightbox.esm.min.js")).default;
        const styleHref = "https:\/\/cdn.jsdelivr.net\/npm\/photoswipe@5.4.4\/dist\/photoswipe.css";

        const styleTag = document.createElement('link');
        styleTag.rel = 'stylesheet';
        styleTag.href = styleHref;
        document.head.appendChild(styleTag);

        const lightbox = new PhotoSwipeLightbox({
            gallerySelector: '.article-content',
            childSelector: 'figure a.image-link',
            pswpModule: () => import("https:\/\/cdn.jsdelivr.net\/npm\/photoswipe@5.4.4\/dist\/photoswipe.esm.min.js")
        });
        lightbox.init();
    }
</script></main></div><script type=text/javascript src=/ts/main.acaf849f2b273f6a8368a58b001f336738d0c948d92e79b116467d0c7515f932.js defer></script></body></html>