<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Cloud on The Cloud Optimist</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/categories/cloud/</link>
        <description>Recent content in Cloud on The Cloud Optimist</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-US</language>
        <lastBuildDate>Sun, 17 May 2026 07:30:00 +0100</lastBuildDate><atom:link href="https://antoinedelia.github.io/cloud-optimist/pr-144/en/categories/cloud/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Cloud Sovereignty: Getting Started with Scaleway</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2026/cloud-sovereignty-getting-started-with-scaleway/</link>
        <pubDate>Sun, 17 May 2026 07:30:00 +0100</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2026/cloud-sovereignty-getting-started-with-scaleway/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/scaleway.png" alt="Featured image of post Cloud Sovereignty: Getting Started with Scaleway" /&gt;</description>
        </item>
        <item>
        <title>The Day I Accidentally Deleted An Api and What It Taught Me About Devops</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2026/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/</link>
        <pubDate>Tue, 17 Feb 2026 07:30:00 +0100</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2026/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2026/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/deleted_api.png" alt="Featured image of post The Day I Accidentally Deleted An Api and What It Taught Me About Devops" /&gt;&lt;p&gt;April 4, 2024, had started off so well. A hot coffee in hand, VS Code humming with activity, and smooth electronic music in my ears—all the ingredients for a perfect day that surely couldn&amp;rsquo;t foreshadow the coming disaster.&lt;/p&gt;
&lt;p&gt;Today, I&amp;rsquo;d like to tell you how a seemingly quiet day became a defining moment in my DevOps career!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/calm_before_storm.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Calm before the storm&#34;
	
	
&gt;&lt;/p&gt;
&lt;h1 id=&#34;incident&#34;&gt;&lt;a href=&#34;#incident&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Incident
&lt;/h1&gt;&lt;h2 id=&#34;the-context&#34;&gt;&lt;a href=&#34;#the-context&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Context
&lt;/h2&gt;&lt;p&gt;At the time, I was working in a team tasked with providing a global API Gateway on AWS, featuring several endpoints managed by different teams. Specifically, setting up this API Gateway was the initial phase of the project. It included a DNS record pointing to the API, the API Gateway itself, and a Cognito Authorizer configured with several clients.&lt;/p&gt;
&lt;p&gt;Once this API was ready, external teams could deploy their own endpoints onto it. To facilitate this, a CI/CD pipeline was in place, using CloudFormation to attach the endpoints directly to the existing API.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’m keeping it as simple as possible here, but if you’re interested in the technical nitty-gritty, feel free to reach out!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On my end, besides being responsible for the global API infrastructure, I occasionally worked on or bootstrapped certain services.&lt;/p&gt;
&lt;h2 id=&#34;the-beginning-of-the-drama&#34;&gt;&lt;a href=&#34;#the-beginning-of-the-drama&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Beginning of the Drama
&lt;/h2&gt;&lt;p&gt;If you’ve ever worked with CloudFormation, you might be familiar with the dreaded &lt;code&gt;UPDATE_ROLLBACK_FAILED&lt;/code&gt; status. This happens when you try to update a CloudFormation stack, but it encounters an error. It then tries to roll back, but if that rollback fails too, your stack gets stuck in &lt;code&gt;UPDATE_ROLLBACK_FAILED&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This state is particularly annoying because you cannot trigger any new deployments until you’ve resolved the underlying issue.&lt;/p&gt;
&lt;p&gt;That is exactly what happened on that fateful April 4, 2024. One of our services got stuck in this state, and I started investigating the &amp;ldquo;why&amp;rdquo; and the &amp;ldquo;how.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;After a few minutes, I noticed the problem stemmed from the API resource itself. Without overthinking it, and in an effort to unblock the situation quickly, I headed straight to the AWS Console, specifically to the API Gateway service. I found the resource in question and rushed to delete it.&lt;/p&gt;
&lt;p&gt;At that exact moment, something very strange happened. An unexpected behavior that made my blood run cold. Instead of staying on the same page, AWS redirected me to the main API Gateway dashboard—the page that lists your available APIs. It now displayed a count of &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I realized then that I hadn&amp;rsquo;t deleted a specific resource &lt;em&gt;within&lt;/em&gt; the API, but the entire API Gateway itself.&lt;/p&gt;
&lt;h2 id=&#34;anatomy-of-a-failure&#34;&gt;&lt;a href=&#34;#anatomy-of-a-failure&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Anatomy of a Failure
&lt;/h2&gt;&lt;p&gt;I never thought I’d make such a rookie mistake. And I imagine as you read this, you’re thinking the same thing.&lt;/p&gt;
&lt;p&gt;Because to get it that wrong, &lt;strong&gt;you really have to try!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let me reconstruct the crime scene for you. Here is what I saw when I decided to delete a resource from the API Gateway.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/api_gateway_view.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;API Gateway resource view&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Any resemblance to an actual situation is entirely coincidental.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In my shoes, which button would you have clicked? Easy! The &lt;em&gt;Delete&lt;/em&gt; button right next to the resource!&lt;/p&gt;
&lt;p&gt;As for me (and I still don&amp;rsquo;t know what possessed me), I chose to click the &lt;em&gt;API actions&lt;/em&gt; button. After all, I did want to perform an &amp;ldquo;action&amp;rdquo;!&lt;/p&gt;
&lt;p&gt;And what happens when you click that button?&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/api_actions.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;API Actions dropdown menu&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Yikes! Right away, you can see it&amp;rsquo;s not what we want at all. But do you think that stopped me? Not a chance! I came here to delete something, and when I saw the word &lt;em&gt;Delete&lt;/em&gt;, I stopped thinking. I should have kept reading, because then I would have seen the word &lt;em&gt;API&lt;/em&gt; right next to it.&lt;/p&gt;
&lt;p&gt;Fortunately, our friends at AWS thought of everything! When you click &lt;em&gt;Delete API&lt;/em&gt;, they still ask if you are absolutely sure. A nice dialog box pops up, showing the name of the API and asking you to type the word &lt;em&gt;confirm&lt;/em&gt; to validate the operation.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/delete_api_dialog.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Delete API confirmation dialog&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all well and good, but the AWS engineers underestimated my impatience. In that moment, the confirmation request wasn&amp;rsquo;t a warning; it was an obstacle to my goal. In a heartbeat, I typed &lt;em&gt;confirm&lt;/em&gt; and hit enter.&lt;/p&gt;
&lt;p&gt;So, here is the last thing I saw before finally realizing the gravity of my mistake:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/the-day-i-accidentally-deleted-an-api-and-what-it-taught-me-about-devops/successfully_deleted_api.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;API successfully deleted&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A vision of pure horror.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I wanted to walk you through this process to make one thing clear: you can put all the safeguards in the world in place, but &lt;strong&gt;you can&amp;rsquo;t protect a system against an impatient individual&lt;/strong&gt;, because they won&amp;rsquo;t stop to read the warnings.&lt;/p&gt;
&lt;p&gt;So, the next time you have to perform an &amp;ldquo;innocuous&amp;rdquo; action, take the time to read and ensure you are actually on the right path.&lt;/p&gt;
&lt;p&gt;That being said, let’s move on to the crucial stage: resolving the incident!&lt;/p&gt;
&lt;h1 id=&#34;resolution&#34;&gt;&lt;a href=&#34;#resolution&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Resolution
&lt;/h1&gt;&lt;h2 id=&#34;the-click&#34;&gt;&lt;a href=&#34;#the-click&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Click
&lt;/h2&gt;&lt;p&gt;Back to the moment of impact. After realizing what had happened, I had a sudden jolt—a moment of clarity (without the aid of any white powder, I promise). I knew what I had to do: resolve the incident, but more importantly, document every single action I took.&lt;/p&gt;
&lt;p&gt;A few weeks prior, I had looked into the &lt;a class=&#34;link&#34; href=&#34;https://about.gitlab.com/blog/postmortem-of-database-outage-of-january-31/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;2017 GitLab incident&lt;/a&gt;, which took the service down for hours and resulted in data loss for some users. That’s how I discovered the concept of a &lt;strong&gt;Post-Mortem&lt;/strong&gt; and why they are so vital in these situations. But I’ll save that for the next section.&lt;/p&gt;
&lt;p&gt;In the meantime, if you&amp;rsquo;re interested in these topics, I highly recommend &lt;a class=&#34;link&#34; href=&#34;https://www.youtube.com/@kevinfaang/videos&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Kevin Fang&amp;rsquo;s YouTube channel&lt;/a&gt; where he, in his own words, &amp;ldquo;reads postmortems and makes low-quality videos about them.&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;rollback-impact-and-communication&#34;&gt;&lt;a href=&#34;#rollback-impact-and-communication&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Rollback, Impact, and Communication
&lt;/h2&gt;&lt;p&gt;My first thought was that there might be a way to trigger a rollback directly within AWS to minimize the impact on users. If I had actually read the warning message earlier, I would have known that was impossible (but if I had read it, I wouldn&amp;rsquo;t have been in this mess anyway).&lt;/p&gt;
&lt;p&gt;With no &amp;ldquo;undo&amp;rdquo; button in sight, I accepted that I was facing a major incident with a global impact. I first set out to map out the full extent of the damage. In my case, not only was the API down (thanks, Captain Obvious), but no new deployments could be made until the API was back online.&lt;/p&gt;
&lt;p&gt;Finally, I made sure to notify the internal team. This kept them in the loop and let them know I was actively working on a fix.&lt;/p&gt;
&lt;h2 id=&#34;analysis-and-troubleshooting&#34;&gt;&lt;a href=&#34;#analysis-and-troubleshooting&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Analysis and Troubleshooting
&lt;/h2&gt;&lt;p&gt;It was time to roll up my sleeves and find a way to redeploy the API Gateway.&lt;/p&gt;
&lt;p&gt;First, I went to the CloudFormation service, remembering that this API was originally deployed through it. I tried updating the stack, hoping it would bring my dear API back like magic.&lt;/p&gt;
&lt;p&gt;Obviously, it wasn&amp;rsquo;t going to be that simple. Updating the stack was impossible because the manual deletion had put the stack into a &amp;ldquo;hybrid&amp;rdquo; state that it couldn&amp;rsquo;t reconcile.&lt;/p&gt;
&lt;p&gt;Since updating was out of the question, the logical next step was to delete the stack and redeploy it from scratch. That’s when the real trouble started. This CloudFormation stack produced several Outputs. &lt;strong&gt;Two of these were required by &amp;ldquo;child&amp;rdquo; stacks&lt;/strong&gt; that had deployed their endpoints on the API. Consequently, CloudFormation blocked me from deleting the stack because it would break all the others.&lt;/p&gt;
&lt;p&gt;After brainstorming alternatives, this heavy interdependence led me to a tough decision: I had to delete all the &amp;ldquo;child&amp;rdquo; stacks in CloudFormation—a total of 81 stacks.&lt;/p&gt;
&lt;p&gt;To make matters worse, these child stacks didn&amp;rsquo;t have identifiable tags that would have allowed us to automate the cleanup. Fortunately, most of them used a recognizable name prefix, which allowed me to clear out the bulk of them manually.&lt;/p&gt;
&lt;p&gt;Did I mention &lt;strong&gt;interdependencies&lt;/strong&gt;? Because we&amp;rsquo;re not done! Some stacks had deployed S3 buckets. And guess what? CloudFormation won&amp;rsquo;t delete a stack if the S3 bucket isn&amp;rsquo;t empty. Naturally, 14 stacks got stuck in &lt;code&gt;DELETE_FAILED&lt;/code&gt;. Luckily, the fix is straightforward: back up each bucket, empty it, and retry the stack deletion.&lt;/p&gt;
&lt;h2 id=&#34;deploying-the-api-light-at-the-end-of-the-tunnel&#34;&gt;&lt;a href=&#34;#deploying-the-api-light-at-the-end-of-the-tunnel&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Deploying the API: Light at the End of the Tunnel?
&lt;/h2&gt;&lt;p&gt;Having finally cleared the web of interdependencies, it was time to delete the original API Gateway stack and redeploy it.&lt;/p&gt;
&lt;p&gt;The deletion went smoothly (thank God), but—naturally—the creation did not.&lt;/p&gt;
&lt;p&gt;First, the stack itself. A YML file existed in a GitHub repo, but &lt;strong&gt;it hadn&amp;rsquo;t been updated in ages&lt;/strong&gt;. I knew I was better off using the stack definition stored within CloudFormation (and yes, I had saved a copy—I&amp;rsquo;m not that crazy).&lt;/p&gt;
&lt;p&gt;This stack didn&amp;rsquo;t just deploy the API Gateway; it handled several AWS resources, including Lambdas. These Lambdas were still running on Python 3.7, a version that &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtimes-deprecated&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS no longer allows for creating new Lambdas&lt;/a&gt;. Fortunately, a quick upgrade to Python 3.12 was enough to satisfy the AWS gods.&lt;/p&gt;
&lt;p&gt;And, to my surprise, the stack finally deployed without a hitch!&lt;/p&gt;
&lt;p&gt;But to keep a long story short, there was still work to do. Several critical resources for the API were missing from the CloudFormation stack. These resources had been created manually in AWS over time, ignoring all Infrastructure as Code best practices (&lt;em&gt;cries in Terraform&lt;/em&gt;). To restore service as quickly as possible (we&amp;rsquo;re DevOps, after all!), I recreated these resources manually once more.&lt;/p&gt;
&lt;p&gt;Finally, several key components had the ARN of the old API hardcoded. This required a bit of &amp;ldquo;digital archaeology&amp;rdquo; to find every spot where a manual update to the new API was needed.&lt;/p&gt;
&lt;p&gt;Ultimately, after several hours of troubleshooting, the API was back up and running, and developers could resume their deployments.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The incident began on April 4, 2024, at 3:24 PM and was resolved on April 5, 2024, at 8:46 AM.&lt;/strong&gt;&lt;/p&gt;
&lt;h1 id=&#34;post-mortem-and-lessons-learned&#34;&gt;&lt;a href=&#34;#post-mortem-and-lessons-learned&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Post-Mortem and Lessons Learned
&lt;/h1&gt;&lt;p&gt;Throughout the incident, I took intensive notes on every action taken. Having heard of the &lt;strong&gt;Post-Mortem&lt;/strong&gt; principle, I knew this incident was the perfect candidate.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re unfamiliar with the concept, a Post-Mortem is a document that retraces the steps of an incident, its impact, and its root cause. But most importantly—and most interestingly—it includes a &lt;strong&gt;Lessons Learned&lt;/strong&gt; section. If you take this part seriously, it will be your best ally in building a more robust architecture.&lt;/p&gt;
&lt;p&gt;In this section, you note three key points: what went well, what went wrong, and where you got lucky. And above all, &lt;strong&gt;be honest!&lt;/strong&gt; Even if some points seem silly or make you look incompetent (and I’m saying this as the guy who manually deleted an API, so take it with a grain of salt), the goal isn&amp;rsquo;t to point fingers (the &amp;ldquo;blameless culture&amp;rdquo;). It’s about understanding the flaws in the system so we can fix them.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;The cost of failure is education.&amp;rdquo; — Devin Carraway (&lt;a class=&#34;link&#34; href=&#34;https://sre.google/sre-book/postmortem-culture/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This might still feel a bit abstract, so let me share my lessons learned from this incident.&lt;/p&gt;
&lt;h2 id=&#34;what-went-well&#34;&gt;&lt;a href=&#34;#what-went-well&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;What went well
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Two things went well&lt;/strong&gt; during this incident.&lt;/p&gt;
&lt;p&gt;First, the resolution was handled by &lt;strong&gt;a team member who knew the architecture inside out&lt;/strong&gt;. This allowed for a quick understanding of what needed to be restored to get the service back online.&lt;/p&gt;
&lt;p&gt;Second, there was &lt;strong&gt;excellent communication throughout&lt;/strong&gt;. When the problem occurred, there was no attempt to hide it. Frequent updates were shared to report on progress. This is crucial—not only does it provide visibility, but communication often leads to helpful tips (like a colleague pointing you toward documentation you didn&amp;rsquo;t know existed).&lt;/p&gt;
&lt;h2 id=&#34;what-went-wrong&#34;&gt;&lt;a href=&#34;#what-went-wrong&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;What went wrong
&lt;/h2&gt;&lt;p&gt;This is the part that hurts. As I mentioned, you have to swallow your pride and highlight everything that could have been handled better.&lt;/p&gt;
&lt;p&gt;For this incident, &lt;strong&gt;four things went wrong&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To start, &lt;strong&gt;the API infrastructure wasn&amp;rsquo;t consolidated in a single file or folder&lt;/strong&gt;; it was scattered across multiple GitHub repos. This made it very difficult to get a bird&amp;rsquo;s-eye view of everything required for the API to function.&lt;/p&gt;
&lt;p&gt;Next, there was a major issue with &lt;strong&gt;drift&lt;/strong&gt;. This refers to the differences between your actual infrastructure and how it’s defined in your code. Ideally, no manual changes should ever occur, and everything should go through your IaC files. Had this been the case, a simple redeployment would have restored the service instantly.&lt;/p&gt;
&lt;p&gt;Another issue was &lt;strong&gt;the heavy interdependence between resources&lt;/strong&gt;. Many relied on CloudFormation stack outputs. Removing the parent stack essentially crippled the ability to manage the rest of the infrastructure.&lt;/p&gt;
&lt;p&gt;Finally, identifying resources tied to our infrastructure was difficult. &lt;strong&gt;Our stack deployed resources without any associated tags&lt;/strong&gt;, making it a scavenger hunt to find every piece of the puzzle.&lt;/p&gt;
&lt;h2 id=&#34;where-we-got-lucky&#34;&gt;&lt;a href=&#34;#where-we-got-lucky&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Where we got lucky
&lt;/h2&gt;&lt;p&gt;This might sound positive, but it isn&amp;rsquo;t! This category covers things that went well &lt;em&gt;only&lt;/em&gt; because of luck. Realize that at any moment, these could have been in the &amp;ldquo;What went wrong&amp;rdquo; column. Be glad this time, but don&amp;rsquo;t let your guard down!&lt;/p&gt;
&lt;p&gt;In this case, &lt;strong&gt;we got lucky in three ways&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;First, the incident was &lt;strong&gt;identified immediately&lt;/strong&gt; (that’s the one perk of making a massive blunder yourself). But it could have been much worse! If the API had been deleted via an automated script, we had no monitoring in place to alert us.&lt;/p&gt;
&lt;p&gt;Second, the person who deleted the API had deep knowledge of the project (yes, I&amp;rsquo;m talking about myself—I have to give myself &lt;em&gt;some&lt;/em&gt; credit). This allowed for an immediate transition into resolution mode, but it could have been someone else who was totally lost.&lt;/p&gt;
&lt;p&gt;Finally, &lt;strong&gt;this was our &amp;ldquo;Dev&amp;rdquo; API&lt;/strong&gt;. The Production API was perfectly fine (a detail I intentionally saved for the end—you know, for the storytelling). So while the impact was minimal, the same incident could have happened in Prod with the same recovery nightmares. And that would have been much more expensive.&lt;/p&gt;
&lt;h2 id=&#34;preparing-for-the-future&#34;&gt;&lt;a href=&#34;#preparing-for-the-future&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Preparing for the Future
&lt;/h2&gt;&lt;p&gt;Now that you&amp;rsquo;ve listed the problems encountered, as a good DevOps engineer, you must learn from them. Note everything that can be improved, but above all, &lt;strong&gt;set a plan!&lt;/strong&gt; Otherwise, these are just empty words.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;A goal without a plan is just a wish.&amp;rdquo; — Antoine de Saint-Exupéry&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In my case, the three key takeaways were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consolidation of Infrastructure as Code:&lt;/strong&gt; Everything must be deployable in the blink of an eye. This is a project I would complete in the following months.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved Monitoring and Alerting:&lt;/strong&gt; If this ever happens again, we need to be alerted immediately so we can react fast.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clearer Documentation:&lt;/strong&gt; Any team member should be able to handle such an incident, and that starts with reliable, understandable docs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All these lessons were tracked as GitHub issues, and I made sure to knock them out over the following months.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;As you&amp;rsquo;ve seen, accidents happen. The key is to make sure they benefit you and your organization. Use them as an opportunity to learn and patch vulnerabilities that were previously undetected (some companies even &lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/Chaos_engineering&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;purposely create chaos&lt;/a&gt; for this very reason).&lt;/p&gt;
&lt;p&gt;Thanks for reading to the end! I’ll leave you here—I’ve got some other infrastructures to delete!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to migrate your State from Terraform Cloud to AWS S3?</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/moving-away-from-terraform-cloud/</link>
        <pubDate>Wed, 17 Dec 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/moving-away-from-terraform-cloud/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/moving-away-from-terraform-cloud/terraform.png" alt="Featured image of post How to migrate your State from Terraform Cloud to AWS S3?" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;When I first started using Terraform (specifically for &lt;a class=&#34;link&#34; href=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/how-i-automated-my-blog-to-the-cloud/&#34; &gt;deploying my blog&lt;/a&gt;), I turned to &lt;strong&gt;Terraform Cloud&lt;/strong&gt; (this name was later changed to HCP Terraform).&lt;/p&gt;
&lt;h1 id=&#34;terraform-and-the-state&#34;&gt;&lt;a href=&#34;#terraform-and-the-state&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Terraform and the State
&lt;/h1&gt;&lt;p&gt;If you know a little bit about Terraform, you are likely familiar with the term &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/language/state&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;em&gt;State&lt;/em&gt;&lt;/a&gt;. This effectively corresponds to the current state of your infrastructure and allows Terraform to know what changes to expect if you modify your Terraform files. This &lt;em&gt;State&lt;/em&gt; is represented by a file: &lt;strong&gt;terraform.tfstate&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;By default, Terraform stores this file locally on your machine, but it recommends using a &lt;em&gt;backend storage&lt;/em&gt; (read: &amp;ldquo;store this file somewhere else, for crying out loud!&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;Obviously, Terraform first suggests the HashiCorp solution: Terraform Cloud. By creating an account, you can use their backend to store your state files for free. Naturally, that is exactly what I did a few years ago.&lt;/p&gt;
&lt;h1 id=&#34;the-end-of-terraform-cloud&#34;&gt;&lt;a href=&#34;#the-end-of-terraform-cloud&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The End of Terraform Cloud
&lt;/h1&gt;&lt;p&gt;Until this week, when I received this email from HashiCorp.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/moving-away-from-terraform-cloud/terraform-mail-free-plan-expiration.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Terraform email announcing the end of the Terraform Cloud Free plan&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Ouch! We should have seen it coming—all good things must come to an end! The free option from back then will soon cease to exist, so I have to make a choice: upgrade my HashiCorp &amp;ldquo;plan,&amp;rdquo; or store my states elsewhere.&lt;/p&gt;
&lt;p&gt;Looking more closely at &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/cloud-docs/overview&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;their current offers&lt;/a&gt;, HashiCorp still proposes a free version, though it is limited in the number of resources that can be deployed (500 currently). It&amp;rsquo;s a fairly generous offer, but not knowing how it might evolve, I&amp;rsquo;ve decided to move my States once and for all.&lt;/p&gt;
&lt;p&gt;Farewell, Terraform Cloud!&lt;/p&gt;
&lt;h1 id=&#34;an-alternative-for-storing-your-states&#34;&gt;&lt;a href=&#34;#an-alternative-for-storing-your-states&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;An alternative for storing your states
&lt;/h1&gt;&lt;p&gt;Fortunately for me, there are plenty of ways to store a Terraform state, thanks to &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/language/state/remote&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Remote State&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To put it simply, you just need to tell Terraform where your state file will be stored. We use the &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/language/backend&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;code&gt;backend&lt;/code&gt; block&lt;/a&gt; to do this.&lt;/p&gt;
&lt;p&gt;There are quite a few options, but since I have an AWS account where I deploy all my resources, I naturally gravitated towards the S3 backend.&lt;/p&gt;
&lt;p&gt;Here is an example of how to configure an S3 backend with Terraform:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-terraform&#34; data-lang=&#34;terraform&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;terraform&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;backend&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;s3&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;bucket&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;mybucket&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;key&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;path/to/my/key/terraform.tfstate&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;region&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;eu-west-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now that we have an alternative, it&amp;rsquo;s time to start the migration!&lt;/p&gt;
&lt;h1 id=&#34;migrating-the-state-to-s3&#34;&gt;&lt;a href=&#34;#migrating-the-state-to-s3&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Migrating the State to S3
&lt;/h1&gt;&lt;p&gt;I&amp;rsquo;ll use the migration of the state I use to deploy this blog as an example.&lt;/p&gt;
&lt;p&gt;Currently, if we look at &lt;a class=&#34;link&#34; href=&#34;https://github.com/antoinedelia/cloud-optimist/blob/4f8f95c177c490e3383c8b554e8d8ca4b3df249b/.github/workflows/main.yml#L28-L33&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;my deployment GitHub Actions workflow&lt;/a&gt;, we can see that I authenticate to my Terraform Cloud account using a token. That part will no longer be necessary (at least for the credentials; the Terraform CLI will still need to be initialized).&lt;/p&gt;
&lt;p&gt;Next, we need to create an S3 bucket to hold the future state files.&lt;/p&gt;
&lt;p&gt;Finally, I&amp;rsquo;ll need to add a &lt;code&gt;backend&lt;/code&gt; block to my project to tell Terraform to stop using Terraform Cloud and start using S3 when accessing the state.&lt;/p&gt;
&lt;p&gt;Hold on, we aren&amp;rsquo;t done yet! If I leave this bucket empty, the next time I try to deploy my blog, Terraform will look for a state that&amp;hellip; doesn&amp;rsquo;t exist! It will assume that no resources have been deployed to my AWS account yet. Consequently, Terraform will try to recreate resources that already exist.&lt;/p&gt;
&lt;p&gt;The last step, therefore, is to retrieve the state file for my blog project and move it into my S3 bucket.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/moving-away-from-terraform-cloud/downloading_terraform_state.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Downloading the Terraform State from Terraform Cloud&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;I then need to ensure that the information I provided in the &lt;code&gt;backend&lt;/code&gt; block matches reality.&lt;/p&gt;
&lt;p&gt;Once everything is ready, it&amp;rsquo;s time to test and deploy!&lt;/p&gt;
&lt;p&gt;I intentionally omitted a few steps in this migration (migrating workspace variables, using GitHub Secrets for the S3 bucket name, adding AWS credentials to GitHub Actions, etc.) to keep this article concise. If you want to see more, check out the &lt;a class=&#34;link&#34; href=&#34;https://github.com/antoinedelia/cloud-optimist/pull/116&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Pull Request I opened&lt;/a&gt; to perform this migration.&lt;/p&gt;
&lt;p&gt;If everything went according to plan, you should see the phrase &lt;code&gt;No changes. Your infrastructure matches the configuration.&lt;/code&gt; appear during your &lt;code&gt;terraform plan&lt;/code&gt;!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;It&amp;rsquo;s always a pain to perform migrations on existing infrastructure. But with a little time and some willpower, it&amp;rsquo;s the kind of task that ultimately only takes a few hours.&lt;/p&gt;
&lt;p&gt;So, don&amp;rsquo;t wait until the last minute—dive in!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How and Why to Set Up AWS IAM Identity Center on Your AWS Account</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/</link>
        <pubDate>Wed, 19 Nov 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/iam-identity-center.jpg" alt="Featured image of post How and Why to Set Up AWS IAM Identity Center on Your AWS Account" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;If you&amp;rsquo;re juggling multiple AWS accounts, or even just a single account with different users, you know that access management can quickly become a &lt;strong&gt;real headache&lt;/strong&gt;. Creating individual IAM users in every account, managing their permissions, ensuring everyone is using MFA&amp;hellip; Phew, just thinking about it is enough to give you cold sweats! But what if I told you there is an elegant, centralized, and much more secure solution to handle all of this? Ladies and Gentlemen, let me introduce you to &lt;strong&gt;IAM Identity Center&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;Ever since I discovered and implemented IAM Identity Center (which some of you might know by its former name, AWS Single Sign-On or AWS SSO), my life as a Cloud admin has changed radically. It&amp;rsquo;s the kind of tool that, once adopted, makes you wonder how you ever lived without it.&lt;/p&gt;
&lt;p&gt;So, what is it exactly, and why is it so great? Let&amp;rsquo;s find out together.&lt;/p&gt;
&lt;h1 id=&#34;iam-identity-center-whats-the-deal&#34;&gt;&lt;a href=&#34;#iam-identity-center-whats-the-deal&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;IAM Identity Center: What&amp;rsquo;s the Deal?
&lt;/h1&gt;&lt;p&gt;Simply put, IAM Identity Center is an AWS service that allows you to centrally manage access to all your AWS accounts and Cloud applications. Whether you have a handful of accounts or a sprawling AWS organization with dozens, or even hundreds of accounts, IAM Identity Center is there to simplify the task for you.&lt;/p&gt;
&lt;p&gt;It offers a single point of entry (a web access portal) for your users, allowing them to access the roles and accounts they are entitled to, all with a single authentication.&lt;/p&gt;
&lt;h1 id=&#34;the-benefits-of-iam-identity-center&#34;&gt;&lt;a href=&#34;#the-benefits-of-iam-identity-center&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Benefits of IAM Identity Center
&lt;/h1&gt;&lt;p&gt;If I sound enthusiastic, it&amp;rsquo;s because the benefits are numerous and significant. To name the most important ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Single Sign-On (SSO):&lt;/strong&gt; Your users log in once via the AWS portal (or via your existing identity provider if you have one) and then access all the accounts and roles assigned to them, without having to re-authenticate for every single account.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Centralized Management:&lt;/strong&gt; You manage all your users, groups, and their permissions (via &amp;ldquo;Permission Sets&amp;rdquo;) from a single place, even if they need to access dozens of different AWS accounts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Temporary Credentials:&lt;/strong&gt; This is one of the most important points! When users access an account via IAM Identity Center, they obtain temporary credentials with a limited lifespan. Say goodbye to lingering IAM Access Keys that pose a major security risk.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MFA (Multi-Factor Authentication):&lt;/strong&gt; You can (and should!) enforce the use of MFA directly at the IAM Identity Center login level.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If I&amp;rsquo;ve piqued your curiosity and you want to know more, check out the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS documentation on IAM Identity Center&lt;/a&gt;. For those who are already sold, let&amp;rsquo;s continue!&lt;/p&gt;
&lt;h1 id=&#34;getting-started-with-iam-identity-center&#34;&gt;&lt;a href=&#34;#getting-started-with-iam-identity-center&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Getting Started with IAM Identity Center
&lt;/h1&gt;&lt;p&gt;Setting up IAM Identity Center is surprisingly simple, especially if you use the built-in Identity Center directory as your identity source. Here are the key steps to get started:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Initial Configuration:&lt;/strong&gt; Head to the AWS console and search for &amp;ldquo;IAM Identity Center&amp;rdquo;. &lt;strong&gt;Heads up:&lt;/strong&gt; choose your AWS region carefully to host IAM Identity Center right from the start, as it is currently complex to change the IAM Identity Center region once configured. The initial setup is often guided and quick. You will choose your identity source (the Identity Center directory, AWS Managed Microsoft AD, or an external provider).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creating Groups and Users:&lt;/strong&gt; Define groups relevant to your organization (e.g., Developers, Administrators, &amp;hellip;). Then create your users and assign them to these groups. If you are using an external IdP, this step will consist of synchronizing your existing users and groups instead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Creating &amp;ldquo;Permission Sets&amp;rdquo;:&lt;/strong&gt; A Permission Set is a collection of permissions (similar to an IAM policy) that you can reuse. You can start from AWS-managed policies (e.g., AdministratorAccess, ReadOnlyAccess) or create your own.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Assigning Access:&lt;/strong&gt; This is where the magic happens. You assign a group (or a user) to one or more AWS accounts, giving them the right to use a specific Permission Set on those accounts. For example, the Developers group might have the &lt;code&gt;PowerUserAccess&lt;/code&gt; Permission Set on the development AWS accounts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enforcing MFA:&lt;/strong&gt; In the IAM Identity Center settings, configure MFA to be mandatory for all your users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sharing the AWS Access URL:&lt;/strong&gt; Every IAM Identity Center configuration has a unique URL for the access portal (e.g., &lt;code&gt;d-xxxxxxxxxx.awsapps.com/start&lt;/code&gt;). This is the URL your users will bookmark to log in.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/aws-iam-identity-center-dashboard.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;AWS IAM Identity Center Dashboard&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Once logged into the portal, users will see the list of AWS accounts and roles (defined by the Permission Sets) they have access to. One click, and they are in the console of the chosen AWS account with the right permissions!&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-and-why-to-set-up-aws-iam-identity-center-on-your-aws-account/aws-iam-identity-center-access-portal.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;AWS IAM Identity Center Access Portal&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;They can also get temporary credentials for the CLI. But speaking of which, how do you connect to an AWS account via CLI using IAM Identity Center? Let&amp;rsquo;s check it out!&lt;/p&gt;
&lt;h1 id=&#34;configuring-cli-access&#34;&gt;&lt;a href=&#34;#configuring-cli-access&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Configuring CLI Access
&lt;/h1&gt;&lt;p&gt;The &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS documentation for configuring CLI authentication with IAM Identity Center&lt;/a&gt; is pretty clear, but I&amp;rsquo;ll walk you through the steps anyway. I&amp;rsquo;m assuming you already have your &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/cli/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS CLI&lt;/a&gt; installed.&lt;/p&gt;
&lt;p&gt;The first and &lt;strong&gt;only&lt;/strong&gt; command to run will be the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aws configure sso
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Next, you will need to enter some information specific to your IAM Identity Center. The most important being the &amp;ldquo;SSO start URL&amp;rdquo; (which you can find in IAM Identity Center under the name &amp;ldquo;AWS access portal URL&amp;rdquo;, a URL ending in &lt;code&gt;/start&lt;/code&gt;). You then need to enter the region where your configuration is located; as for the &amp;ldquo;SSO registration scopes&amp;rdquo;, you can leave the default value.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SSO session name &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;Recommended&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;: default
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SSO start URL &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;None&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;https://xxxxxxxxxxxx.awsapps.com/start&lt;span class=&#34;o&#34;&gt;](&lt;/span&gt;https://xxxxxxxxxxxx.awsapps.com/start&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SSO region &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;None&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: eu-west-1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SSO registration scopes &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;sso:account:access&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If everything goes well, a window should open in your browser to validate your identity. Once that&amp;rsquo;s done, head back to your terminal.&lt;/p&gt;
&lt;p&gt;In my case, I only have one AWS account, and IAM Identity Center selects it for me by default. But you might have a choice of which AWS account to select. The same goes for the role.&lt;/p&gt;
&lt;p&gt;Finally, choose a profile name to use for your future API calls. I advise you to use &lt;code&gt;default&lt;/code&gt;, which will allow you to avoid adding &lt;code&gt;--profile my-aws-profile&lt;/code&gt; to the end of every command.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;The only AWS account available to you is: xxxxxxxxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Using the account ID xxxxxxxxxxxx
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;The only role available to you is: AdministratorAccess
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Using the role name &lt;span class=&#34;s2&#34;&gt;&amp;#34;AdministratorAccess&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Default client Region &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;None&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: eu-west-1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CLI default output format &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;json &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; not specified&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;None&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: json
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Profile name &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;AdministratorAccess-xxxxxxxxxxxx&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;: default
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;The AWS CLI is now configured to use the default profile.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Run the following &lt;span class=&#34;nb&#34;&gt;command&lt;/span&gt; to verify your configuration:
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aws sts get-caller-identity
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;And there you go, you&amp;rsquo;re all set!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;As you might have gathered, I am a big fan of AWS IAM Identity Center. It brings an indispensable layer of security while considerably simplifying access management, whether for administrators or users.&lt;/p&gt;
&lt;p&gt;It is a true pillar for a well-managed and secure AWS infrastructure. If you aren&amp;rsquo;t using it yet, I strongly encourage you to explore setting it up. It&amp;rsquo;s a minimal time investment for huge gains in security and efficiency.&lt;/p&gt;
&lt;p&gt;Your infrastructure (and your security teams) will thank you!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>On The Trail of The Lost Resource - My Investigation With Athena and CloudTrail</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/on-the-trail-of-the-lost-resource-my-investigation-with-athena-and-cloudtrail/</link>
        <pubDate>Wed, 09 Jul 2025 12:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/on-the-trail-of-the-lost-resource-my-investigation-with-athena-and-cloudtrail/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/on-the-trail-of-the-lost-resource-my-investigation-with-athena-and-cloudtrail/aws_lost_resource.jpeg" alt="Featured image of post On The Trail of The Lost Resource - My Investigation With Athena and CloudTrail" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;Recently, I had to play detective in our AWS account.&lt;/p&gt;
&lt;p&gt;A resource was there (a Cognito User Pool), plain as day, but nobody could remember where it came from. And of course, there were no tags to help us (if only they had read &lt;a class=&#34;link&#34; href=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/why-tagging-your-aws-resources-is-a-must/&#34; &gt;my post on why tagging your AWS resources is a must&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;My mission, should I choose to accept it: find out who created it. The problem? The event was about four months old.&lt;/p&gt;
&lt;p&gt;My first instinct was to turn to AWS CloudTrail. And there, I hit my first wall: &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events.html#event-history-limitations&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;the event history is only viewable for the last 90 days&lt;/a&gt;. Dead end.&lt;/p&gt;
&lt;p&gt;Luckily, I knew our CloudTrail logs were archived in an S3 bucket. My first thought was to manually download the archives for the right month, unzip dozens of JSON files, and hit &lt;kbd&gt;Ctrl+F&lt;/kbd&gt; while praying for a miracle. Let&amp;rsquo;s just say it was neither efficient, pleasant, nor fast.&lt;/p&gt;
&lt;p&gt;So, I wondered if there wasn&amp;rsquo;t a simpler way to search through this pile of logs, and I finally found the perfect solution: &lt;strong&gt;AWS Athena&lt;/strong&gt;.&lt;/p&gt;
&lt;h1 id=&#34;querying-your-s3-logs-with-athena&#34;&gt;&lt;a href=&#34;#querying-your-s3-logs-with-athena&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Querying your S3 logs with Athena
&lt;/h1&gt;&lt;p&gt;For those unfamiliar, &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/athena/latest/ug/what-is.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Athena&lt;/a&gt; is an interactive query service that makes it easy to analyze data directly in Amazon S3 using standard SQL. Basically, you can run queries on files (JSON, CSV, etc.) as if they were in a traditional database. No more downloading anything!&lt;/p&gt;
&lt;p&gt;The idea, then, is to &amp;ldquo;map&amp;rdquo; our CloudTrail logs stored in S3 to a table in Athena. To do this, we use a single &lt;code&gt;CREATE EXTERNAL TABLE&lt;/code&gt; query. Following &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/athena/latest/ug/create-cloudtrail-table-partition-projection.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;the AWS documentation on the subject&lt;/a&gt;, I ran the following query in the Athena console.&lt;/p&gt;
&lt;p&gt;This query creates a table and uses a very handy feature called &amp;ldquo;partition projection.&amp;rdquo; This allows Athena to infer the location of the logs based on the date, without having to manually manage partitions. This is very convenient when the structure is standardized, as is the case with AWS CloudTrail.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;CREATE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;EXTERNAL&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;TABLE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cloudtrail_logs_pp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventversion&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;useridentity&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRUCT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventtime&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventsource&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventname&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;awsregion&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;requestparameters&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;responseelements&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;additionaleventdata&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;requestid&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventid&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resources&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;ARRAY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRUCT&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;accountid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventtype&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventcategory&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;STRING&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;PARTITIONED&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;BY&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;timestamp&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;ROW&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FORMAT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SERDE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;org.apache.hive.hcatalog.data.JsonSerDe&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;STORED&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;INPUTFORMAT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;com.amazon.emr.cloudtrail.CloudTrailInputFormat&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;OUTPUTFORMAT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;LOCATION&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://BUCKET-NAME/AWSLogs/ACCOUNT-ID/CloudTrail/REGION&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- Replace with your S3 bucket path
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;TBLPROPERTIES&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;projection.enabled&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;projection.timestamp.format&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;yyyy/MM/dd&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;projection.timestamp.interval&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;projection.timestamp.interval.unit&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;DAYS&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;projection.timestamp.range&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2024/01/01,NOW&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- Replace with your start date
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;projection.timestamp.type&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;date&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;storage.location.template&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;s3://BUCKET-NAME/AWSLogs/ACCOUNT-ID/CloudTrail/REGION/${timestamp}&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;-- Replace with your S3 bucket path
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; Don&amp;rsquo;t forget to replace the &lt;code&gt;s3://...&lt;/code&gt; URLs with the exact path to your S3 bucket where your CloudTrail logs are stored, and to adjust the &lt;code&gt;projection.timestamp.range&lt;/code&gt; property to the period you&amp;rsquo;re interested in.&lt;/p&gt;
&lt;h1 id=&#34;investigation-time-finding-the-information&#34;&gt;&lt;a href=&#34;#investigation-time-finding-the-information&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Investigation Time: Finding the Information
&lt;/h1&gt;&lt;p&gt;Once the table is created (which only takes a few seconds), the hardest part is over! My investigation could finally begin.&lt;/p&gt;
&lt;p&gt;I was looking for who had created a Cognito &lt;code&gt;UserPoolClient&lt;/code&gt; on a specific date. So my SQL query looked like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sql&#34; data-lang=&#34;sql&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;SELECT&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventTime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventName&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;userIdentity&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;arn&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;FROM&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cloudtrail_logs_pp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;WHERE&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;timestamp&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;2025/02/25&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;AND&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;eventName&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;CreateUserPoolClient&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In just a few seconds, Athena scanned the logs for the requested day and returned the result.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/on-the-trail-of-the-lost-resource-my-investigation-with-athena-and-cloudtrail/running_the_athena_query.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Athena query to search CloudTrail logs in S3&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;I had the exact time, the event, and most importantly, the ARN of the user who performed the action. Mission accomplished!&lt;/p&gt;
&lt;h1 id=&#34;the-verdict-and-the-culprit&#34;&gt;&lt;a href=&#34;#the-verdict-and-the-culprit&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Verdict&amp;hellip; and the Culprit
&lt;/h1&gt;&lt;p&gt;The funniest part of this story?&lt;/p&gt;
&lt;p&gt;After setting up this solution and finding the information so easily, I discovered that the &amp;ldquo;culprit&amp;rdquo; who had created this resource four months ago&amp;hellip; &lt;strong&gt;was me&lt;/strong&gt;. I had completely forgotten!&lt;/p&gt;
&lt;p&gt;Jokes aside, this experience confirmed one thing for me: taking a few minutes to set up Athena on your CloudTrail logs is an incredibly worthwhile investment. You&amp;rsquo;re giving yourself a long-term auditing and search capability that will save you hours of manual searching the day you really need it. Don&amp;rsquo;t be like me; don&amp;rsquo;t wait until you&amp;rsquo;re stuck to set it up!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Why Tagging your AWS Resources is a Must?</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/why-tagging-your-aws-resources-is-a-must/</link>
        <pubDate>Tue, 24 Jun 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/why-tagging-your-aws-resources-is-a-must/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/why-tagging-your-aws-resources-is-a-must/aws_tagging.jpeg" alt="Featured image of post Why Tagging your AWS Resources is a Must?" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;The more services we deploy on AWS, the easier it is to get lost. At first, we know all the services we use by heart, the number of Lambdas or EC2 instances running. But little by little, it&amp;rsquo;s easy to feel overwhelmed, especially when different projects pile up. Quickly finding which resources belong to which project, or identifying those that weren&amp;rsquo;t properly cleaned up after a PoC, can quickly become a headache. And that&amp;rsquo;s without even mentioning cost visibility!
Fortunately, there&amp;rsquo;s a simple yet incredibly powerful practice: &lt;strong&gt;tagging&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In this article, I want to show you that a good tagging strategy is &lt;strong&gt;crucial for your organization, the way you handle cost, and to secure&lt;/strong&gt; your AWS account.&lt;/p&gt;
&lt;p&gt;Ready? Tag along with me!&lt;/p&gt;
&lt;h1 id=&#34;why-are-tags-useful&#34;&gt;&lt;a href=&#34;#why-are-tags-useful&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Why are tags useful?
&lt;/h1&gt;&lt;p&gt;Imagine labels on moving boxes. Without them, it&amp;rsquo;s impossible to know what&amp;rsquo;s inside or which room they belong to. Tags on AWS are the same! A tag is a piece of &lt;strong&gt;information&lt;/strong&gt; (in key-value format) that you assign to your resources (EC2 instances, S3 buckets, RDS databases, etc.).
A good tagging strategy allows you to, among other things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Identify orphan resources&lt;/strong&gt;: This is the classic scenario. A resource without a &lt;code&gt;Project&lt;/code&gt; or &lt;code&gt;Owner&lt;/code&gt; tag? There&amp;rsquo;s a good chance it has been forgotten and is consuming resources (and therefore money) for nothing. Listing untagged (or poorly tagged) resources is an essential first step in cleaning up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Allocate costs&lt;/strong&gt;: By tagging your resources with a project identifier, cost center, or team, you can then use AWS Cost Explorer to filter your expenses and understand precisely which projects consume the most. This is essential for internal chargebacks or simply for optimizing your budget.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automate actions&lt;/strong&gt;: Tags can serve as triggers for automation scripts (for example, backing up all EC2 instances with the tag &lt;code&gt;Backup=Daily&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manage access and security&lt;/strong&gt;: The &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/iam&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS IAM&lt;/a&gt; service can use tags to grant granular permissions.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In short, tagging is the foundation of &lt;strong&gt;good Cloud governance&lt;/strong&gt;. For more details, I invite you to consult the &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/solutions/guidance/tagging-on-aws/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;tagging guide proposed by AWS&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Fortunately, we can associate multiple tags with the same resource. But this raises the question: how many tags are necessary?&lt;/p&gt;
&lt;p&gt;This will depend on your company and each project, but overall, there are some tags that won&amp;rsquo;t hurt, no matter your situation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Project&lt;/strong&gt;: The name of the project linked to the resource. Usually, the GitHub repository name works well.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment&lt;/strong&gt;: The desired environment (dev, uat, prod, &amp;hellip;). Even if you have separate AWS accounts, this will help you identify if a resource got lost during deployment.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Owner&lt;/strong&gt;: The owner of the resource. This could be a person, but more ideally a team (frontend, backend, security, &amp;hellip;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Depending on your use case, you&amp;rsquo;ll surely have other ideas for tags, but with the ones above, you&amp;rsquo;ll already have a good start! And in case of doubt, feel free to read the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/tag-editor/latest/userguide/best-practices-and-strats.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;tagging best practices from AWS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s now look at some concrete examples of using tags in AWS.&lt;/p&gt;
&lt;h2 id=&#34;aws-cost-explorer-tracking-costs-thanks-to-tags&#34;&gt;&lt;a href=&#34;#aws-cost-explorer-tracking-costs-thanks-to-tags&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;AWS Cost Explorer: Tracking costs thanks to tags
&lt;/h2&gt;&lt;p&gt;One of the most concrete benefits of tagging is the &lt;strong&gt;visibility it provides over your expenses&lt;/strong&gt;. &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/aws-cost-management/aws-cost-explorer/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Cost Explorer&lt;/a&gt; is the tool of choice for this.&lt;/p&gt;
&lt;p&gt;Once your resources are correctly tagged (for example, with the &lt;code&gt;Project&lt;/code&gt; tag), you need to activate these tags for cost allocation in the AWS Billing and Cost Management console (Billing and Cost Management -&amp;gt; Cost Organization -&amp;gt; Cost Allocation Tags). Be aware that there might be a delay before the activated tags appear in Cost Explorer.&lt;/p&gt;
&lt;p&gt;Once activated, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Filter by tag&lt;/strong&gt;: In Cost Explorer, you can filter your costs by the value of a specific tag.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Group by tag&lt;/strong&gt;: You can also choose to group your expenses by tag. This will give you an overview of the cost distribution across different projects, environments, etc.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create budgets based on tags&lt;/strong&gt;: With AWS Budgets, you can set alert thresholds for costs associated with specific tags, helping you avoid nasty surprises.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/why-tagging-your-aws-resources-is-a-must/cost_explorer_tag_filtering.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Example of filtering by tag&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example of filtering by tag for my blog: the costs are minimal, am I a FinOps expert?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This ability to dissect your AWS bill by tags transforms cost management from an obscure chore into a transparent and controllable exercise. It&amp;rsquo;s a must for any organization concerned about its Cloud budget. You can now add &lt;em&gt;FinOps&lt;/em&gt; to your LinkedIn bio!&lt;/p&gt;
&lt;h2 id=&#34;aws-resource-explorer-keeping-an-eye-on-deployed-resources&#34;&gt;&lt;a href=&#34;#aws-resource-explorer-keeping-an-eye-on-deployed-resources&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;AWS Resource Explorer: Keeping an eye on deployed resources
&lt;/h2&gt;&lt;p&gt;Now that we are convinced of the usefulness of tags, how do we &lt;strong&gt;list all the resources that use a specific tag?&lt;/strong&gt; We will see this together, with one part in the AWS console, and another part in the terminal (for all the geeks reading this article!).&lt;/p&gt;
&lt;h3 id=&#34;visual-exploration-in-the-aws-console&#34;&gt;&lt;a href=&#34;#visual-exploration-in-the-aws-console&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Visual exploration in the AWS console
&lt;/h3&gt;&lt;p&gt;If you are not yet familiar with &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/resourceexplorer/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Resource Explorer&lt;/a&gt;, now is the time to discover it! This relatively recent service allows you to search and discover your AWS resources across all regions of your account, using a simple interface, much like a search engine.&lt;/p&gt;
&lt;p&gt;The main advantage of Resource Explorer is its ability to give you a unified view. No more jumping from region to region. You activate indexing, and then you can search for your resources by name, ID, and of course&amp;hellip; by tag!&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s an excellent tool for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Getting a quick overview.&lt;/li&gt;
&lt;li&gt;Visually exploring resources associated with a specific tag.&lt;/li&gt;
&lt;li&gt;Quickly identifying resources without having to code anything.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To use it, activate it in the desired regions (or all of them), let it index your resources, and then use the search bar with a syntax like &lt;code&gt;tag.key:Project tag.value:Cloud*&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/why-tagging-your-aws-resources-is-a-must/resource_explorer_search_tags.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Searching resources by tag&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Example of a tag search for my blog: only three resources manage this blog!&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&#34;a-more-technical-approach-with-aws-cli&#34;&gt;&lt;a href=&#34;#a-more-technical-approach-with-aws-cli&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;A more technical approach with AWS CLI
&lt;/h3&gt;&lt;p&gt;For those who, like me, like to have control via the command line, or who need to automate these searches, the &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/cli/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS CLI&lt;/a&gt; remains a key ally. More specifically, it&amp;rsquo;s the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;resourcegroupstaggingapi&lt;/a&gt; service that will interest us.&lt;/p&gt;
&lt;p&gt;The key command is &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/get-resources.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;get-resources&lt;/a&gt;. Here is a typical example to list the ARNs of all resources having the tag Project with the value &amp;ldquo;Cloud Antoine Delia&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;aws resourcegroupstaggingapi get-resources &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    --tag-filters &lt;span class=&#34;s2&#34;&gt;&amp;#34;Key=Project,Values=Cloud Antoine Delia&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; jq &lt;span class=&#34;s2&#34;&gt;&amp;#34;[.ResourceTagMappingList[].ResourceARN]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Which gives us:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;arn:aws:s3:::antoiXXXXXXXXXXXXX&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s break it down a bit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aws resourcegroupstaggingapi get-resources&lt;/code&gt;: This is the API call; so far, so good.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--tag-filters &amp;quot;Key=Project,Values=Cloud Antoine Delia&amp;quot;&lt;/code&gt;: This is where we specify our filter. We are looking for the tag Project with the value &amp;ldquo;Cloud Antoine Delia&amp;rdquo;. You can add multiple filters.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;| jq &amp;quot;[.ResourceTagMappingList[].ResourceARN]&amp;quot;&lt;/code&gt;: &lt;a class=&#34;link&#34; href=&#34;https://jqlang.org/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;jq&lt;/a&gt; is a wonderful tool for manipulating JSON on the command line. Here, we use it to cleanly extract the list of ARNs of the found resources (you can do without it, but why make life difficult?).&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Hey, wait a minute! In the console, you show us three resources, and now there&amp;rsquo;s only one! Where&amp;rsquo;s the catch?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well spotted! You should know that when you make your API call, you are using &lt;strong&gt;a default region&lt;/strong&gt;. However, if you have resources in various regions, you will need to specify it. Thus, if we add &lt;code&gt;--region us-east-1&lt;/code&gt; just before the jq pipe, we indeed get our two missing resources.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;arn:aws:acm:us-east-1:6XXXXXXXXXXX0:certificate/f4ca3b13-XXXXXXXXXXXXX&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;arn:aws:cloudfront::6XXXXXXXXXXX0:distribution/ERSXXXXXXXXXX&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Besides this detail that you must not forget, this command is extremely powerful because you can integrate it into scripts to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate regular reports on resources by project.&lt;/li&gt;
&lt;li&gt;Automatically detect resources that do not comply with your tagging policy.&lt;/li&gt;
&lt;li&gt;Combine with other AWS CLI commands to perform actions on the listed resources.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, you could list all your resources of a certain type (e.g., all your EC2 instances) and check which ones are missing essential tags.&lt;/p&gt;
&lt;p&gt;And if you&amp;rsquo;re wondering if AWS doesn&amp;rsquo;t already offer a service for this&amp;hellip; It does! But we will talk about that in a future article (for the curious, I&amp;rsquo;m talking about &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/config/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Config&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&#34;aws-iam-securing-the-use-of-your-resources&#34;&gt;&lt;a href=&#34;#aws-iam-securing-the-use-of-your-resources&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;AWS IAM: Securing the use of your resources
&lt;/h2&gt;&lt;p&gt;Your resources are deployed in AWS, and now you want to give a team permission to manage all of that.
But here&amp;rsquo;s the thing, in your AWS account, you also have critical resources that must absolutely not be compromised.&lt;/p&gt;
&lt;p&gt;AWS IAM is here for you! Using a simple policy, you can specify that &lt;strong&gt;only resources with a certain tag can be modified&lt;/strong&gt; by a user or group.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take the following example: you would like to allow a team to start or stop certain EC2 instances, but prevent them from accidentally stopping a critical EC2 instance!
You just need to add the following policy to your users:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;Version&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2012-10-17&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;Statement&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Sid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;AllowStartStopEC2IfProjectCloud&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Effect&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Allow&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Action&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;ec2:StartInstances&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;s2&#34;&gt;&amp;#34;ec2:StopInstances&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Resource&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;arn:aws:ec2:*:*:instance/*&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Condition&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nt&#34;&gt;&amp;#34;StringEquals&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;          &lt;span class=&#34;nt&#34;&gt;&amp;#34;aws:ResourceTag/Project&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Cloud Antoine Delia&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Sid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;AllowDescribeToSeeInstances&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Effect&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Allow&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Action&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ec2:DescribeInstances&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;Resource&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Thus, your users will be autonomous in using their resources, without having the possibility to impact other resources.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;You&amp;rsquo;ve understood it: a rigorous tagging strategy &lt;strong&gt;isn&amp;rsquo;t an option; it&amp;rsquo;s a necessity&lt;/strong&gt; for operating serenely on AWS. Whether on the organizational, financial, or security management level, AWS gives you the means to take full advantage of your tags.&lt;/p&gt;
&lt;p&gt;So, a little piece of advice: if you haven&amp;rsquo;t already, &lt;strong&gt;define a clear tagging policy&lt;/strong&gt; in your organization, apply it, and use these tools to regularly check that everything is in order. You&amp;rsquo;ll thank me later!&lt;/p&gt;
</description>
        </item>
        <item>
        <title>AWS Lambda: INIT Phase To Be Billed Soon - Should We Be Alarmed?</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/aws-lambdas-init-phase-to-be-billed-soon-should-we-be-alarmed/</link>
        <pubDate>Tue, 13 May 2025 07:30:00 +0200</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/aws-lambdas-init-phase-to-be-billed-soon-should-we-be-alarmed/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/fr/posts/2025/aws-lambdas-init-phase-to-be-billed-soon-should-we-be-alarmed/lambda-init-billing.jpeg" alt="Featured image of post AWS Lambda: INIT Phase To Be Billed Soon - Should We Be Alarmed?" /&gt;&lt;h1 id=&#34;introduction&#34;&gt;&lt;a href=&#34;#introduction&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Introduction
&lt;/h1&gt;&lt;p&gt;Ah, Lambdas. Probably my favorite AWS service! Almost instantly, they allow you to create a small script or even a fully hosted API backend in the Cloud, all at a low cost thanks to the &amp;ldquo;pay-as-you-go&amp;rdquo; model. But is it too good to be true?&lt;/p&gt;
&lt;p&gt;A few days ago, &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/blogs/compute/aws-lambda-standardizes-billing-for-init-phase&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS announced a change in how the Lambda initialization phase is billed&lt;/a&gt;. &lt;strong&gt;Starting August 1, 2025&lt;/strong&gt;, this phase will systematically be included in the billed duration calculation, for &lt;em&gt;all&lt;/em&gt; Lambdas.&lt;/p&gt;
&lt;p&gt;If you weren&amp;rsquo;t aware, until now, if you used Lambda functions packaged as ZIP archives with AWS-managed runtimes (like Python, Node.js, etc.), the duration of this &lt;code&gt;INIT&lt;/code&gt; phase wasn&amp;rsquo;t billed. It was a small &amp;ldquo;gift&amp;rdquo; from AWS (quite nice of them). But all good things must come to an end, and we will now have to pay for this initialization time for our Lambdas.&lt;/p&gt;
&lt;p&gt;So, will this make using Lambdas too expensive? And how can we minimize this initialization part as much as possible? Today, let&amp;rsquo;s explore these questions!&lt;/p&gt;
&lt;h1 id=&#34;understanding-the-lambda-lifecycle&#34;&gt;&lt;a href=&#34;#understanding-the-lambda-lifecycle&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Understanding the Lambda Lifecycle
&lt;/h1&gt;&lt;p&gt;Before diving into billing, it&amp;rsquo;s a good opportunity to recall the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lambda lifecycle&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For simplicity, I won&amp;rsquo;t go into the details of &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-extensions.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lambda Extensions&lt;/a&gt; and &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lambda SnapStart&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It consists of three main phases:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;INIT:&lt;/strong&gt; This is the &amp;ldquo;cold start&amp;rdquo; phase. When a new instance of your function needs to be created to handle a request, Lambda prepares the environment. This phase lasts a maximum of 10 seconds.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;INVOKE:&lt;/strong&gt; This is where your code (the function handler) is executed to process the request.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SHUTDOWN:&lt;/strong&gt; When the execution environment hasn&amp;rsquo;t been used for a certain period, the Lambda shuts down to free up resources. If a new request arrives, the Lambda will have to go through the INIT phase again.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/aws-lambdas-init-phase-to-be-billed-soon-should-we-be-alarmed/lambda_lifecycle.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Lambda Lifecycle&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;During the &lt;code&gt;INIT&lt;/code&gt; phase, &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html#runtimes-lifecycle-ib&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;your Lambda performs several actions&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Retrieves your code (from S3 for a ZIP, or ECR for a Docker image).&lt;/li&gt;
&lt;li&gt;Configures the environment with the allocated memory, chosen runtime, etc.&lt;/li&gt;
&lt;li&gt;Starts the runtime (&lt;code&gt;Runtime INIT&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Executes the static code of your function (everything outside the handler, like initializing global variables or &lt;code&gt;boto3&lt;/code&gt;) (&lt;code&gt;Function INIT&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key takeaway here is that the &lt;code&gt;INIT&lt;/code&gt; phase only occurs during a &lt;em&gt;cold start&lt;/em&gt;. If a request arrives while an execution environment is already &amp;ldquo;warm&amp;rdquo; (ready and reused), this phase is skipped, and execution goes directly to the &lt;code&gt;INVOKE&lt;/code&gt; phase. This is called a &amp;ldquo;warm start,&amp;rdquo; which is much faster.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;AWS doesn&amp;rsquo;t disclose its logic for transitioning a Lambda from &amp;lsquo;warm&amp;rsquo; to &amp;lsquo;cold&amp;rsquo;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;the-billing-change-in-detail&#34;&gt;&lt;a href=&#34;#the-billing-change-in-detail&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Billing Change in Detail
&lt;/h1&gt;&lt;p&gt;Currently, &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/lambda/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lambda billing&lt;/a&gt; is based on two factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The number of requests.&lt;/li&gt;
&lt;li&gt;The execution duration of your code, rounded up to the nearest millisecond (the cost of this duration depends on the memory allocated to the function).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Until August 1, 2025, for functions packaged as ZIPs with managed runtimes, the &lt;code&gt;INIT&lt;/code&gt; phase duration was not counted in the &amp;ldquo;Billed Duration&amp;rdquo;. This could be seen in CloudWatch logs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Before August 1, 2025
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Note that Billed Duration is the rounded-up value
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;of Duration without considering Init Duration
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;REPORT RequestId: xxxxx   Duration: 250.06 ms   Billed Duration: 251 ms   Init Duration: 100.77 ms
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;After August 1, 2025
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Billed Duration is now the rounded-up value
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;of Duration + Init Duration
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;REPORT RequestId: xxxxx   Duration: 250.06 ms   Billed Duration: 351 ms   Init Duration: 100.77 ms
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;As you can see, AWS will now take your Init Duration into account in addition to the Duration when calculating the Billed Duration.&lt;/p&gt;
&lt;h1 id=&#34;what-impact-on-the-bill&#34;&gt;&lt;a href=&#34;#what-impact-on-the-bill&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;What Impact on the Bill?
&lt;/h1&gt;&lt;p&gt;So, this all sounds interesting, but will this change break the bank?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take an example to see more clearly. Imagine a Python Lambda configured with 1024 MB of memory, deployed in the &lt;code&gt;eu-west-1&lt;/code&gt; (Ireland) region.&lt;/p&gt;
&lt;p&gt;Assume the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Lambda receives 10 million invocations per month.&lt;/li&gt;
&lt;li&gt;The cold start rate is 1% (&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html#cold-start-latency&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;average provided by AWS&lt;/a&gt;), meaning 100,000 cold starts per month.&lt;/li&gt;
&lt;li&gt;The average invocation duration (&lt;code&gt;Duration&lt;/code&gt;) is 3 seconds.&lt;/li&gt;
&lt;li&gt;The average initialization duration (&lt;code&gt;Init Duration&lt;/code&gt;) is 1 second.&lt;/li&gt;
&lt;li&gt;Cost per request: $0.20 per million requests.&lt;/li&gt;
&lt;li&gt;Duration cost (x86): $0.0000166667 per GB-second.&lt;/li&gt;
&lt;/ul&gt;
&lt;details&gt;
  &lt;summary&gt;Details of the calculation&lt;/summary&gt;
&lt;p&gt;&lt;strong&gt;Cost Calculation BEFORE August 1, 2025:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Request Cost:&lt;/strong&gt; 10 million req * ($0.20 / 1 million req) = &lt;strong&gt;$2.00&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Duration Cost:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Warm starts (9.9 million): Billed duration = 3 seconds.&lt;/li&gt;
&lt;li&gt;Cold starts (100,000): Billed duration = 3 seconds (INIT not billed).&lt;/li&gt;
&lt;li&gt;Total billed duration (seconds): (9,900,000 * 3 s) + (100,000 * 3 s) = 29,700,000 seconds + 300,000 seconds = 30,000,000 seconds.&lt;/li&gt;
&lt;li&gt;Total GB-seconds: 30,000,000 seconds * (1024 MB / 1024 MB) = 30,000,000 GB-s.&lt;/li&gt;
&lt;li&gt;Duration Cost: 30,000,000 GB-s * $0.0000166667/GB-s = &lt;strong&gt;$500.00&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total Monthly Cost (Before):&lt;/strong&gt; $2.00 + $500.00 = &lt;strong&gt;$502.00&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Cost Calculation AFTER August 1, 2025:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Request Cost:&lt;/strong&gt; &lt;strong&gt;$2.00&lt;/strong&gt; (unchanged)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Duration Cost:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Warm starts (9.9 million): Billed duration = 3 seconds.&lt;/li&gt;
&lt;li&gt;Cold starts (100,000): Billed duration = 3 seconds (&lt;code&gt;Duration&lt;/code&gt;) + 1 second (&lt;code&gt;Init Duration&lt;/code&gt;) = 4 seconds.&lt;/li&gt;
&lt;li&gt;Total billed duration (seconds): (9,900,000 * 3 s) + (100,000 * 4 s) = 29,700,000 seconds + 400,000 seconds = 30,100,000 seconds.&lt;/li&gt;
&lt;li&gt;Total GB-seconds: 30,100,000 seconds * (1024 MB / 1024 MB) = 30,100,000 GB-s.&lt;/li&gt;
&lt;li&gt;Duration Cost: 30,100,000 GB-s * $0.0000166667/GB-s = &lt;strong&gt;$501.67&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total Monthly Cost (After):&lt;/strong&gt; $2.00 + $501.67 = &lt;strong&gt;$503.67&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/details&gt;
&lt;p&gt;In this specific scenario, the increase is only &lt;strong&gt;$1.67 per month&lt;/strong&gt;. This is indeed minimal and confirms AWS&amp;rsquo;s communication. But be careful, as the &lt;em&gt;actual&lt;/em&gt; impact will strongly depend on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The memory allocated to your Lambdas (more memory = higher cost per ms).&lt;/li&gt;
&lt;li&gt;The actual duration of your &lt;code&gt;INIT&lt;/code&gt; phase.&lt;/li&gt;
&lt;li&gt;Your cold start rate (can be higher if your traffic is irregular).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Therefore, it&amp;rsquo;s wise to check with your own numbers!&lt;/p&gt;
&lt;p&gt;Below is a small script that will allow you to quickly test this on your side.&lt;/p&gt;
&lt;details&gt;
  &lt;summary&gt;Python Script&lt;/summary&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;92
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;calculate_lambda_costs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total_invocations_per_month&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;cold_start_rate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;average_init_duration_sec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;allocated_memory_mb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# Changed GB to MB for consistency with common AWS console values&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;cost_per_million_requests&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;cost_per_gb_second&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0000166667&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;num_cold_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_invocations_per_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cold_start_rate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;num_warm_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_invocations_per_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_cold_starts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;request_cost&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_invocations_per_month&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1_000_000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_per_million_requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;allocated_memory_gb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allocated_memory_mb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1024&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# Convert MB to GB for calculation&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Duration cost BEFORE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;billed_duration_warm_starts_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_warm_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# For cold starts, only invocation duration was billed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;billed_duration_cold_starts_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_cold_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total_billed_duration_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;billed_duration_warm_starts_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;billed_duration_cold_starts_sec_before&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total_gb_seconds_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_billed_duration_sec_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allocated_memory_gb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;duration_cost_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_gb_seconds_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_per_gb_second&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total_monthly_cost_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request_cost&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duration_cost_before&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# Duration cost AFTER&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;billed_duration_warm_starts_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_warm_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     &lt;span class=&#34;c1&#34;&gt;# For cold starts, invocation + init duration will be billed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;billed_duration_cold_starts_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;num_cold_starts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;average_init_duration_sec&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total_billed_duration_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;billed_duration_warm_starts_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;billed_duration_cold_starts_sec_after&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total_gb_seconds_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_billed_duration_sec_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;allocated_memory_gb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;duration_cost_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_gb_seconds_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_per_gb_second&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total_monthly_cost_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request_cost&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;duration_cost_after&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_monthly_cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total_monthly_cost_after&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;display_results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_after&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;cost_difference&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;Estimated monthly cost BEFORE change: $&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Estimated monthly cost AFTER change: $&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_after&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Estimated monthly cost increase: $&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_difference&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_difference&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;percentage_increase&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_difference&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Percentage increase: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;percentage_increase&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.2f&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;%&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;elif&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_difference&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Percentage increase: Infinite (original cost was zero)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;AWS Lambda Cost Calculator (Before/After Init Duration Pricing Change)&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Please enter the values for your scenario or press Enter to use default values.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;default_invocations&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10_000_000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;default_cold_start_rate&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.01&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# 1%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;default_invocation_duration&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.0&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# seconds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;default_init_duration&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1.0&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# seconds&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;default_memory_mb&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;1024.0&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;# 1024 MB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;invocations_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Total invocations per month (default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_invocations&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;): &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;total_invocations_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invocations_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;invocations_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_invocations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;cold_start_rate_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Cold start rate (e.g., 0.01 for 1%, default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_cold_start_rate&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;): &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;cold_start_rate_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cold_start_rate_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cold_start_rate_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_cold_start_rate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;invocation_duration_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Average invocation duration in seconds (default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_invocation_duration&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;): &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;invocation_duration_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invocation_duration_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;invocation_duration_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_invocation_duration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;init_duration_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Average initialization duration in seconds (default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_init_duration&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;): &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;init_duration_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;init_duration_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;init_duration_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_init_duration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;memory_mb_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Memory allocated to Lambda in MB (e.g., 512, default: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;default_memory_mb&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;): &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;memory_mb_input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memory_mb_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;memory_mb_str&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;default_memory_mb&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_after&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;calculate_lambda_costs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;total_invocations_per_month&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_invocations_input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;cold_start_rate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cold_start_rate_input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;average_invocation_duration_sec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;invocation_duration_input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;average_init_duration_sec&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;init_duration_input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;allocated_memory_mb&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;memory_mb_input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;display_results&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cost_before&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cost_after&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;ValueError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;Error: Please enter valid numbers.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;ne&#34;&gt;Exception&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;An unexpected error occurred: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/details&gt;
&lt;h1 id=&#34;how-to-monitor-your-init-phase-and-estimate-the-impact&#34;&gt;&lt;a href=&#34;#how-to-monitor-your-init-phase-and-estimate-the-impact&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;How to Monitor Your INIT Phase and Estimate the Impact?
&lt;/h1&gt;&lt;p&gt;A script is nice, but if you have a bunch of Lambdas to check, you might find the task exhausting.&lt;/p&gt;
&lt;p&gt;Fortunately, AWS provides some tools to check this efficiently. As seen earlier, each Lambda will generate a &lt;code&gt;REPORT&lt;/code&gt; log containing its &lt;code&gt;Init Duration&lt;/code&gt;. We can easily aggregate this information using CloudWatch Logs Insights. And the icing on the cake, AWS even provides us with the right query.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;filter @type = &amp;#34;REPORT&amp;#34; and @billedDuration &amp;lt; ceil(@duration + @initDuration)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;| stats sum((@memorySize/1024/1000) * (@billedDuration/1000)) as BilledGBs,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        sum((@memorySize/1024/1000) * ((ceil(@duration + @initDuration) - @billedDuration)/1000)) as EstimatedInitGBs,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        (EstimatedInitGBs / (EstimatedInitGBs + BilledGBs)) * 100 as EstimatedInitCostPercent
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;Keep in mind that CloudWatch Logs Insights is billed at $0.005 per GB of data scanned (&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/cloudwatch/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;source&lt;/a&gt;). Adjust the query time range to limit costs.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Just run this query on your Lambda log groups (using the &lt;code&gt;/aws/lambda&lt;/code&gt; prefix or specific function prefixes), and you&amp;rsquo;ll get a result like this:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;BilledGBs&lt;/th&gt;
          &lt;th&gt;UnbilledInitGBs&lt;/th&gt;
          &lt;th&gt;Ratio&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;512.8007&lt;/td&gt;
          &lt;td&gt;86.6699&lt;/td&gt;
          &lt;td&gt;0.1446&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;This query gives you three key pieces of information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BilledGBs&lt;/code&gt;: The total GB-seconds currently billed.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EstimatedInitGBs&lt;/code&gt;: The total GB-seconds consumed during the &lt;code&gt;INIT&lt;/code&gt; phase that were not previously billed (this is an estimation based on the difference between current billed duration and potential future billed duration including &lt;code&gt;INIT&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EstimatedInitCostPercent&lt;/code&gt;: The percentage that these previously unbilled &lt;code&gt;INIT&lt;/code&gt; GB-seconds represent compared to the total consumed GB-seconds (current billed + estimated init). This approximates the potential percentage increase in your duration costs due to the change.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In our example, the cost share of the &lt;code&gt;INIT&lt;/code&gt; phase represents approximately &lt;strong&gt;14%&lt;/strong&gt; of the total execution cost (current + potential init cost)! Depending on your current bill, this could be significant.&lt;/p&gt;
&lt;h1 id=&#34;understanding-and-optimizing-your-lambda&#34;&gt;&lt;a href=&#34;#understanding-and-optimizing-your-lambda&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Understanding and Optimizing Your Lambda
&lt;/h1&gt;&lt;p&gt;Okay, so you know you might have to pay more. But aren&amp;rsquo;t there levers we can pull to reduce this increase in your bill?&lt;/p&gt;
&lt;p&gt;Here are some tips for making the best use of this INIT phase and thus reducing your future costs.&lt;/p&gt;
&lt;h2 id=&#34;strategically-use-the-init-phase&#34;&gt;&lt;a href=&#34;#strategically-use-the-init-phase&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Strategically Use the INIT Phase
&lt;/h2&gt;&lt;p&gt;Your first instinct might be to remove all the &lt;code&gt;INIT&lt;/code&gt; code (code outside the handler) and put it in your handler. That way, no more &lt;code&gt;INIT&lt;/code&gt; billing! But not only would you just be shifting the problem (because executing that code will still be billed), it would be even worse, because now even your &amp;lsquo;warm start&amp;rsquo; Lambda executions would have to process this code!&lt;/p&gt;
&lt;p&gt;Yes, remember that the code in the &lt;code&gt;INIT&lt;/code&gt; phase is executed &lt;em&gt;only&lt;/em&gt; during cold starts. Therefore, it&amp;rsquo;s the ideal place for expensive initialization operations that can be reused by subsequent (&amp;ldquo;warm start&amp;rdquo;) invocations. This is even &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html#function-code&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;recommended by AWS&lt;/a&gt;. Thus, the &lt;code&gt;INIT&lt;/code&gt; phase is perfect for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Importing heavy libraries or dependencies.&lt;/li&gt;
&lt;li&gt;Establishing connections to other AWS services (S3, DynamoDB, etc.) via SDKs (&lt;code&gt;boto3&lt;/code&gt; for Python).&lt;/li&gt;
&lt;li&gt;Creating database connection pools.&lt;/li&gt;
&lt;li&gt;Fetching parameters or secrets from Systems Manager Parameter Store or Secrets Manager.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maximize this initialization phase to reduce the execution time of Lambdas running in &amp;lsquo;warm start&amp;rsquo;.&lt;/p&gt;
&lt;h2 id=&#34;optimize-package-size&#34;&gt;&lt;a href=&#34;#optimize-package-size&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Optimize Package Size
&lt;/h2&gt;&lt;p&gt;This is often the simplest lever, because sometimes we import all sorts of things into our Lambda. So, make sure to include only strictly necessary dependencies. Also, be sure to exclude anything related to your development environment (I can&amp;rsquo;t tell you how many times I&amp;rsquo;ve found a &lt;code&gt;node_modules&lt;/code&gt; or &lt;code&gt;tests&lt;/code&gt; folder in Lambdas&amp;hellip;). Finally, don&amp;rsquo;t hesitate to consult AWS articles, as &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/blogs/developer/reduce-lambda-cold-start-times-migrate-to-aws-sdk-for-javascript-v3/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;some directly tackle the subject of cold starts&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;lambda-snapstart&#34;&gt;&lt;a href=&#34;#lambda-snapstart&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Lambda SnapStart
&lt;/h2&gt;&lt;p&gt;Available for Java, .NET, and Python runtimes, &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;SnapStart&lt;/a&gt; is a very interesting feature for combating cold starts. When you enable it, Lambda takes a &amp;ldquo;snapshot&amp;rdquo; of the initialized execution environment &lt;em&gt;after&lt;/em&gt; the first &lt;code&gt;INIT&lt;/code&gt; phase. For subsequent cold starts, Lambda restores this snapshot instead of redoing the entire &lt;code&gt;INIT&lt;/code&gt; phase, saving you significant time.&lt;/p&gt;
&lt;p&gt;I imagine reading about this feature, you&amp;rsquo;re thinking &amp;ldquo;Wow, this is great, I&amp;rsquo;m going to enable this feature on all my Lambdas!&amp;rdquo;. Except there are a few subtleties to be aware of.&lt;/p&gt;
&lt;p&gt;Firstly, SnapStart is currently &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html#snapstart-runtimes&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;only compatible with specific versions of certain languages&lt;/a&gt; (Python 3.12 minimum, NodeJS not supported&amp;hellip;). The same goes for regions; &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html#snapstart-supported-regions&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;only a limited number support this feature&lt;/a&gt; at the time of writing. Finally, &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/lambda/pricing/#SnapStart_Pricing&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;this feature is not free&lt;/a&gt; and incurs its own costs. Make sure to check the potential cost if you want to enable it on your Lambdas.&lt;/p&gt;
&lt;h2 id=&#34;provisioned-concurrency&#34;&gt;&lt;a href=&#34;#provisioned-concurrency&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Provisioned Concurrency
&lt;/h2&gt;&lt;p&gt;If your application has predictable traffic or if cold start latency is unacceptable, you can use &amp;ldquo;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Provisioned Concurrency&lt;/a&gt;&amp;rdquo;. You ask Lambda to keep a certain number of execution environments pre-initialized (warm) at all times.&lt;/p&gt;
&lt;p&gt;Advantage: Requests hitting these provisioned instances &lt;em&gt;never&lt;/em&gt; experience a cold start. The &lt;code&gt;INIT&lt;/code&gt; phase is done upfront, before the first request.&lt;/p&gt;
&lt;p&gt;Disadvantage: You pay for the time these environments are provisioned, &lt;em&gt;whether they receive requests or not&lt;/em&gt;. The &lt;code&gt;INIT&lt;/code&gt; phase is also billed during this pre-initialization.&lt;/p&gt;
&lt;p&gt;Here too, it&amp;rsquo;s up to you to see if it&amp;rsquo;s worth enabling this on some of your key Lambdas!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;The upcoming change in billing for Lambda&amp;rsquo;s &lt;code&gt;INIT&lt;/code&gt; phase on &lt;strong&gt;August 1, 2025&lt;/strong&gt;, is primarily a standardization. For the majority of Lambdas (specifically those using managed runtimes and ZIP packaging that previously benefited from the free init), this means the duration of this phase will now be added to the billed duration during cold starts.&lt;/p&gt;
&lt;p&gt;Even if the financial impact will likely be small for you, it&amp;rsquo;s an excellent opportunity to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understand your Lambda&amp;rsquo;s lifecycle and what happens during initialization.&lt;/li&gt;
&lt;li&gt;Measure the &lt;code&gt;INIT&lt;/code&gt; phase duration of your critical functions using CloudWatch tools.&lt;/li&gt;
&lt;li&gt;Optimize this phase if necessary, by reducing package sizes, using SnapStart, or considering Provisioned Concurrency for specific use cases.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, don&amp;rsquo;t wait until August! Familiarize yourself with CloudWatch Logs Insights now. This will allow you to identify which Lambdas to optimize first and avoid any nasty surprises on your AWS bill.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How I Automated My Blog To The Cloud</title>
        <link>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/how-i-automated-my-blog-to-the-cloud/</link>
        <pubDate>Tue, 04 Mar 2025 07:30:00 +0100</pubDate>
        
        <guid>https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/how-i-automated-my-blog-to-the-cloud/</guid>
        <description>&lt;img src="https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/how-i-automated-my-blog-to-the-cloud/automated-blog.jpeg" alt="Featured image of post How I Automated My Blog To The Cloud" /&gt;&lt;h1 id=&#34;how-it-started-and-why-it-ended&#34;&gt;&lt;a href=&#34;#how-it-started-and-why-it-ended&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;How it started and why it ended
&lt;/h1&gt;&lt;p&gt;When I started blogging, I was still in engineering school. And the world of websites and blogs was still new to me. So when I wanted to create a personal blog, I turned to what I thought was the best solution at the time: WordPress.&lt;/p&gt;
&lt;p&gt;Like it or not, &lt;strong&gt;WordPress is quite easy to use&lt;/strong&gt; for beginners, even more for me who was still discovering how to host a website at the time.&lt;/p&gt;
&lt;p&gt;So, with a brand new OVH account, I was able to quickly setup my &lt;a class=&#34;link&#34; href=&#34;https://blog.antoinedelia.fr&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;personal blog&lt;/a&gt; in a few clicks!&lt;/p&gt;
&lt;p&gt;And when the time came where I wanted to create a blog dedicated to professional topics, I naturally came back to my ol&amp;rsquo; friend WordPress.&lt;/p&gt;
&lt;p&gt;But after some months, the glory of WordPress started to fade into a darker view. Sure, it was convenient to add a new post by going through WordPress&amp;rsquo; UI, but maintaining the website was always boresome. Moreover, a WordPress installation requires using a database, which incurred a higher bill at the end of each month.&lt;/p&gt;
&lt;p&gt;All of this for a blog that I knew did not receive many visits each day.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/struggling_blog.jpeg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;The struggle with WordPress&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Surely there was a better way to do this.&lt;/p&gt;
&lt;h1 id=&#34;the-start-of-a-new-plan&#34;&gt;&lt;a href=&#34;#the-start-of-a-new-plan&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The start of a new plan
&lt;/h1&gt;&lt;p&gt;I will tell you here the path that led me to the rebirth of my blog on which you are today. If you are only interested in the technical details, you can &lt;a class=&#34;link&#34; href=&#34;#technically-what-i-have-today&#34; &gt;move on to the next section&lt;/a&gt;. Otherwise, happy reading!&lt;/p&gt;
&lt;h2 id=&#34;discovering-hugo&#34;&gt;&lt;a href=&#34;#discovering-hugo&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Discovering Hugo
&lt;/h2&gt;&lt;p&gt;Before searching for a new tool, I tried to think of what I needed.&lt;/p&gt;
&lt;p&gt;My blog was essentially a simple webpage, a static website with no fancy JavaScript or stuff like that. Plus, there was no backend to handle API calls for user authentication for example, so &lt;strong&gt;I could simply not use any database at all&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;So what I needed was essentially a way to focus on the content of the blog, and make sure I could attach to it a nice theme, and that was it!&lt;/p&gt;
&lt;p&gt;But, as I&amp;rsquo;m an engineer, so in essence, a real bad designer, I wanted to avoid having to deal with CSS as much as possible. Again, I wanted to focus on the content, rather than the looks. So I searched and searched for the perfect tool. And I didn&amp;rsquo;t had to look too long to find it: &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/hugo.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Hugo logo&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Upon arriving on its website, I was greeted by an intriguing message message: &lt;strong&gt;The world’s fastest framework for building websites&lt;/strong&gt;. Surely, I was curious, and dug into the documentation. And oh boy, was I not disappointed.&lt;/p&gt;
&lt;p&gt;This was exactly what I wanted. A framework where I had to write in markdown format, that would be converted to HTML for me. Plus, it came with &lt;a class=&#34;link&#34; href=&#34;https://themes.gohugo.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;a bunch of themes&lt;/a&gt;, so I didn&amp;rsquo;t even had to bother about the design. I could just pick one that I liked, and move on.&lt;/p&gt;
&lt;p&gt;So, without losing any more time, I started to convert my WordPress blog to a Hugo site. I came across a handy script called &lt;a class=&#34;link&#34; href=&#34;https://github.com/SchumacherFM/wordpress-to-hugo-exporter&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;wordpress-to-hugo-exporter&lt;/a&gt; that converted my whole Wordpress database into compatible markdown syntax, and I was ready to go!&lt;/p&gt;
&lt;p&gt;Now I needed to host this website somewhere.&lt;/p&gt;
&lt;h2 id=&#34;a-new-challenger-aws&#34;&gt;&lt;a href=&#34;#a-new-challenger-aws&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;A new challenger: AWS
&lt;/h2&gt;&lt;p&gt;In parallel, I had an opportunity working for a company that focused on the Cloud, more specifically &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/aws.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;AWS logo&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;At the time, Cloud was brand new to me. But I was hearing more and more about it, and I wanted to check what was all the fuss around it. Would this be a true life-changer, as people would call it, or would it be yet again another buzz word, and become a dying trend?&lt;/p&gt;
&lt;p&gt;Long story short, &lt;strong&gt;AWS was (and still is) amazing!&lt;/strong&gt; Not only was it an amazing discovery, I could simply not see a world without Cloud anymore.&lt;/p&gt;
&lt;p&gt;The more I learned about all these amazing AWS services, the more I thought: &lt;strong&gt;isn&amp;rsquo;t there a way for me to leverage the Cloud to host my blog?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With that in mind, I started looking for options that AWS provided. And because of my recent discovery of Hugo, my website did not needed PHP anymore, nor any database to work. It was now a simple, static website, which could perfectly fit in an S3 bucket.&lt;/p&gt;
&lt;p&gt;Not only does AWS has a &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;documentation about hosting a static website on an S3 bucket&lt;/a&gt;, but &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/s3/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;the pricing for it was just a few cents&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I had found an easy and cost-effective way to host my website.&lt;/p&gt;
&lt;p&gt;The last point that was bothering me, is that to setup all of this, I had to create an S3 bucket, configure it, add a CDN with AWS CloudFront, take into account certificates with AWS ACM, and finally create a DNS record in AWS Route53. So many actions that, if done manually, could make it super difficult to reproduce this setup if I had to do it again.&lt;/p&gt;
&lt;p&gt;I needed a robust way to configure this infrastructure.&lt;/p&gt;
&lt;h2 id=&#34;terraform-to-the-rescue&#34;&gt;&lt;a href=&#34;#terraform-to-the-rescue&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Terraform to the rescue
&lt;/h2&gt;&lt;p&gt;When you start learning Cloud, you will usually hear about &lt;a class=&#34;link&#34; href=&#34;https://en.wikipedia.org/wiki/Infrastructure_as_code&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Infrastructure as Code&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The idea is simple: describe your Cloud infrastructure with&amp;hellip; code! (yes, as the name stands by).&lt;/p&gt;
&lt;p&gt;The benefits of using an IaC tool, is that you will be able to keep track of the changes done on your infrastructure (like you would do with code in GitHub).&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s say that someone wants to update the configuration of an AWS service. This person goes to the AWS console and start making their changes. But after some trial and error, they decide to give up for now, and to go back to the initial state. And here is the problem: they don&amp;rsquo;t know exactly how it was before! And unless they took note of the initial state before making their changes, they will, again, have to do a bunch of trial and errors before going back to the beginning.&lt;/p&gt;
&lt;p&gt;All of that could have been prevented if the infrastructure was configured through an IaC tool to begin with. In such a case, a simple automated deploy could have done the trick!&lt;/p&gt;
&lt;p&gt;There are a bunch of IaC tools out there. But how can I not talk about the most popular one, the one that made IaC a standard in the Cloud ecosystem: &lt;a class=&#34;link&#34; href=&#34;https://www.terraform.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Terraform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/terraform.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Terraform logo&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;Terraform, as you could have guessed, is an Infrastructure as Code tool with a declarative approach, meaning that you have to declare the state of the infrastructure you wish to deploy. To do that, you need ton use a specific language: hcl (which stands for HashiCorp Configuration Language). Here is an example to create an S3 bucket with Terraform.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-terraform&#34; data-lang=&#34;terraform&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;resource&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws_s3_bucket&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;example&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;bucket&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;my-tf-test-bucket&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;tags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;Name&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;My bucket&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;Environment&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Dev&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s go back to my blog! Terraform seems to be the perfect tool to configure the infrastructure that will host my blog. All I had to do was to go through an architecture step to know which AWS services I needed, and how to interconnect them, before translating that to Terraform.&lt;/p&gt;
&lt;p&gt;And here is the architecture diagram I came up with.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/blog_architecture_diagram.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Architecture diagram of my blog hosted on AWS, deployed with Terraform&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;All of this was perfect, but I realized one thing. Every time I needed to add a post, or update the infrastructure, I had to clone my repository, make the appropriate changes, and do a lot of manual actions to update my blog.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say that I was not too pleased with that, and I intended to fix that!&lt;/p&gt;
&lt;h2 id=&#34;forget-copy-and-paste-with-github-actions&#34;&gt;&lt;a href=&#34;#forget-copy-and-paste-with-github-actions&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Forget copy and paste with GitHub Actions
&lt;/h2&gt;&lt;p&gt;Like I said before, my website was ready. The last step I needed was about &lt;strong&gt;the deployment&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For now, when I had to create a new post, I had to manually build my Hugo website, and move the generated files to my S3 bucket. What a waste of time and energy!&lt;/p&gt;
&lt;p&gt;So I explored the topic of CI/CD pipelines to make my life easy (if you&amp;rsquo;re interested in this topic, I suggest reading &lt;a class=&#34;link&#34; href=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/en/posts/2025/how-we-built-a-cicd-strategy-that-onboards-100-python-projects-in-under-a-minute/&#34; &gt;my post about setting up a CI/CD strategy&lt;/a&gt;). While Jenkins tried to get my attention, I decided to go with the obvious choice: &lt;a class=&#34;link&#34; href=&#34;https://github.com/features/actions&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/github_actions.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;GitHub Actions logo&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;GitHub Actions are simple CI/CD pipelines that you can define directly in your GitHub repository. The main benefit, is that you do not need any additional account, nor to install anything: all is included! In addition, GitHub Actions use an easy-to-read YAML syntax (in opposition to Jenkins and its horrifying groovy!).&lt;/p&gt;
&lt;p&gt;So I created a pipeline that was able to configure Terraform in case I made any modifications, and could also build and deploy my website automatically in my S3 bucket when I updated or added a post.&lt;/p&gt;
&lt;p&gt;All the steps were looking good, mission accomplished!&lt;/p&gt;
&lt;h1 id=&#34;technically-what-i-have-today&#34;&gt;&lt;a href=&#34;#technically-what-i-have-today&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Technically: What I Have Today
&lt;/h1&gt;&lt;p&gt;My blog is now fully automated and deploys to AWS!&lt;/p&gt;
&lt;p&gt;If you want to dive into it, everything is publicly available on my GitHub repository: &lt;a class=&#34;link&#34; href=&#34;https://github.com/antoinedelia/cloud-optimist&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/antoinedelia/cloud-optimist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, let me show you more details about it.&lt;/p&gt;
&lt;h2 id=&#34;project-structure&#34;&gt;&lt;a href=&#34;#project-structure&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Project Structure
&lt;/h2&gt;&lt;p&gt;The project structure is as follow:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cloud-optimist/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── .github/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── workflows/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│       └── main.yml  &lt;span class=&#34;c1&#34;&gt;# GitHub Actions&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── cloud/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── ...  &lt;span class=&#34;c1&#34;&gt;# My Hugo blog&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── terraform/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── ...  &lt;span class=&#34;c1&#34;&gt;# The Terraform configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── README.md
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;As you can see, I split my project into three key directories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.github&lt;/code&gt; : contains the &lt;code&gt;main.yml&lt;/code&gt; file which defines the GitHub Actions CI/CD steps&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cloud&lt;/code&gt; : contains my Hugo blog&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terraform&lt;/code&gt; : contains all the Terraform infrastructure&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-github-actions&#34;&gt;&lt;a href=&#34;#the-github-actions&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The GitHub Actions
&lt;/h2&gt;&lt;p&gt;My GitHub Actions is rather simple, and can be divided into multiple steps.&lt;/p&gt;
&lt;h3 id=&#34;the-initialization-step&#34;&gt;&lt;a href=&#34;#the-initialization-step&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Initialization Step
&lt;/h3&gt;&lt;p&gt;Let&amp;rsquo;s have a look at the top of the file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Build and Deploy&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;push&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;branches&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;master&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;pull_request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;jobs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;build-and-deploy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Build &amp;amp; Deploy&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;runs-on&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;ubuntu-latest&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;environment&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;production&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;defaults&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;shell&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;bash&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;cloud&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Here, I ask GitHub to run the pipeline on the &lt;code&gt;master&lt;/code&gt; branch, or if I have a Pull Request. Let me reassure you, I do not deploy anything to production with a Pull Request. You&amp;rsquo;ll see below that this only allows me to perform some &amp;ldquo;dry-run&amp;rdquo; checks and ensure no issues are found before I can safely deploy to production via the &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;
&lt;p&gt;I also ask GitHub to use &lt;code&gt;bash&lt;/code&gt; and to use the &lt;code&gt;cloud&lt;/code&gt; directory as the default working directory.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see what&amp;rsquo;s next:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;actions/checkout@v3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;dorny/paths-filter@v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;filter&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;filters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;          web:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;            - &amp;#39;cloud/**&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;          terraform:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;sd&#34;&gt;            - &amp;#39;terraform/**&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This step is crucial if you wish to fasten your CI/CD and ultimately save cost.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m using the &lt;a class=&#34;link&#34; href=&#34;https://github.com/dorny/paths-filter&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;dorny/paths-filter&lt;/a&gt; actions which allows me to &lt;strong&gt;detect which files were modified in the last commit&lt;/strong&gt;. In my case, I look for the &lt;code&gt;cloud&lt;/code&gt; and &lt;code&gt;terraform&lt;/code&gt; directories. This way, if no changes were detected on the Terraform side, no need to trigger the Terraform steps in my pipeline. In the same way, if the directory &lt;code&gt;cloud&lt;/code&gt; is untouched, no need to try to build and deploy the contents of my blog. This will save you few cents related to the data transfer pricing to your AWS S3 bucket (no need to thanks me!).&lt;/p&gt;
&lt;p&gt;The next steps speak for themselves.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Checkout the repository to the GitHub Actions runner&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Checkout&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;actions/checkout@v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Update Git Submodules&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;git submodule update --init --recursive&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;I simply get the content of my repository and update the submodules. This last step was useful back when I was using submodules to handle my Hugo themes. I now use the &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/hugo-modules/use-modules/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo Modules&lt;/a&gt;, which could let me remove this step altogether.&lt;/p&gt;
&lt;h3 id=&#34;the-terraform-step&#34;&gt;&lt;a href=&#34;#the-terraform-step&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Terraform Step
&lt;/h3&gt;&lt;p&gt;Let&amp;rsquo;s continue with Terraform:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Install the latest version of Terraform CLI and configure the Terraform CLI configuration file with a Terraform Cloud user API token&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Setup Terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;hashicorp/setup-terraform@v1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;cli_config_credentials_token&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.TF_API_TOKEN }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Initialize a new or existing Terraform working directory by creating initial files, loading any remote state, downloading modules, etc.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Terraform Init&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;terraform init&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Checks that all Terraform configuration files adhere to a canonical format&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Terraform Format&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;terraform fmt -check&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# Generates an execution plan for Terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Terraform Plan&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;terraform plan&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;c&#34;&gt;# On push to master, build or change infrastructure according to Terraform configuration files&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Terraform Apply&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;working-directory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;./terraform&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39; &amp;amp;&amp;amp; github.ref == &amp;#39;refs/heads/master&amp;#39; &amp;amp;&amp;amp; github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;terraform apply -auto-approve&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now that&amp;rsquo;s a long step! Let&amp;rsquo;s break it down.&lt;/p&gt;
&lt;p&gt;The first thing that should&amp;rsquo;ve catch your attention is this line:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.terraform == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Do you remember? This is what allows us to tell if files were updated in the &lt;code&gt;terraform&lt;/code&gt; directory. Here, I check if I need to run these steps or not.&lt;/p&gt;
&lt;p&gt;Then, I am running some ordinary Terraform commands: &lt;code&gt;terraform init&lt;/code&gt; to initialize my project, &lt;code&gt;terraform fmt -check&lt;/code&gt; to ensure my code is fancy, and finally &lt;code&gt;terraform plan&lt;/code&gt; to look at the changes planned.&lt;/p&gt;
&lt;p&gt;Last but not least, &lt;code&gt;terraform apply -auto-approve&lt;/code&gt;, which will deploy the changes to my AWS infrastructure. But if you look closely, you will notice I added two extra checks:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;l&#34;&gt;github.ref == &amp;#39;refs/heads/master&amp;#39; &amp;amp;&amp;amp; github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This ensures that &lt;strong&gt;this step will only be ran if the event is a &lt;code&gt;push&lt;/code&gt; on the &lt;code&gt;master&lt;/code&gt; branch&lt;/strong&gt;. This way, no need to worry about an unwanted deployment when I simply play with my infrastructure on another branch or in a Pull Request. Phew!&lt;/p&gt;
&lt;h3 id=&#34;the-hugo-and-aws-steps&#34;&gt;&lt;a href=&#34;#the-hugo-and-aws-steps&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Hugo and AWS Steps
&lt;/h3&gt;&lt;p&gt;Now that my infrastructure is ready, it is time to publish my blog!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Build&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;actions/setup-node@v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.web == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;sudo wget https://github.com/gohugoio/hugo/releases/download/v0.142.0/hugo_extended_0.142.0_linux-amd64.deb -O hugo.deb&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;sudo dpkg --install ./hugo.deb&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;hugo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;nt&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;Deploy to AWS&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;uses&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;jakejarvis/s3-sync-action@master&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.web == &amp;#39;true&amp;#39; &amp;amp;&amp;amp; github.ref == &amp;#39;refs/heads/master&amp;#39; &amp;amp;&amp;amp; github.event_name == &amp;#39;push&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;with&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;args&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;--&lt;span class=&#34;l&#34;&gt;acl public-read --follow-symlinks --delete&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;      &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AWS_S3_BUCKET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.AWS_S3_BUCKET }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.AWS_ACCESS_KEY_ID }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;${{ secrets.AWS_SECRET_ACCESS_KEY }}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;AWS_REGION&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;eu-west-1&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;SOURCE_DIR&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;cloud/public/&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;As for Terraform, we check if any modifications were done on the blog.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yml&#34; data-lang=&#34;yml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;steps.filter.outputs.web == &amp;#39;true&amp;#39;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then, I&amp;rsquo;m retrieving an extended version of Hugo straight from the GitHub release (here the v0.142.0). I&amp;rsquo;m installing it and build my blog using the &lt;code&gt;hugo&lt;/code&gt; command.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This step could be simplified using the &lt;a class=&#34;link&#34; href=&#34;https://github.com/peaceiris/actions-hugo&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;peaceiris/actions-hugo&lt;/a&gt; actions&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finally, I&amp;rsquo;m using the &lt;a class=&#34;link&#34; href=&#34;https://github.com/jakejarvis/s3-sync-action&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;jakejarvis/s3-sync-action&lt;/a&gt; actions (I realized while writing this post that this action has been archived a couple of days before, ouch! &amp;ndash; I&amp;rsquo;ll add an edit later to mention an alternative) to move my blog&amp;rsquo;s files into my S3 bucket.&lt;/p&gt;
&lt;p&gt;Of course, you&amp;rsquo;ll have to store some credentials in your GitHub repository so that your GitHub Actions can be authorized to use AWS, but nothing too crazy.&lt;/p&gt;
&lt;p&gt;We are now done with the GitHub Actions part!&lt;/p&gt;
&lt;h2 id=&#34;the-terraform-part&#34;&gt;&lt;a href=&#34;#the-terraform-part&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Terraform part
&lt;/h2&gt;&lt;p&gt;Regarding Terraform, I&amp;rsquo;ll keep it short, as this is not too complex.&lt;/p&gt;
&lt;p&gt;There is one personal choice here, is that &lt;strong&gt;I prefer to split my &lt;code&gt;.tf&lt;/code&gt; files based on the AWS services used&lt;/strong&gt;, rather than putting them all in a single &lt;code&gt;main.tf&lt;/code&gt; file, which could make it hard to read. In the end, I have an &lt;code&gt;s3.tf&lt;/code&gt; file for all resources linked to the S3 service, a &lt;code&gt;cloudfront.tf&lt;/code&gt; file for everything related to CloudFront, and so on.&lt;/p&gt;
&lt;p&gt;One important information, is that &lt;strong&gt;it is necessary to define at least the &lt;code&gt;us-east-1&lt;/code&gt; region&lt;/strong&gt;, as you must deploy your ACM certificates there. For the rest, I&amp;rsquo;m deploying all my resources in the &lt;code&gt;eu-west-1&lt;/code&gt; region. To make this split, I&amp;rsquo;m using the &lt;a class=&#34;link&#34; href=&#34;https://developer.hashicorp.com/terraform/language/providers/configuration#alias-multiple-provider-configurations&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Terraform alias&lt;/a&gt;. Here&amp;rsquo;s an example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-terraform&#34; data-lang=&#34;terraform&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# The default configuration: all resources starting with `aws_` will use this provider
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;provider&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;region&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;eu-west-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;provider&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;region&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;us-east-1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;alias&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;us_east_1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;resource&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws_s3_bucket&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;site&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;bucket&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;bucket_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;force_destroy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;resource&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;aws_acm_certificate&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;cert&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;provider&lt;/span&gt;                  &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;aws&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;us_east_1&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;  # Will be deployed in us-east-1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;domain_name&lt;/span&gt;               &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;domain_name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;subject_alternative_names&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;*.&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;domain_name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;validation_method&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DNS&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;the-hugo-part&#34;&gt;&lt;a href=&#34;#the-hugo-part&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;The Hugo part
&lt;/h2&gt;&lt;p&gt;My Hugo blog is based on the &lt;a class=&#34;link&#34; href=&#34;https://themes.gohugo.io/themes/hugo-theme-stack/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Stack theme&lt;/a&gt;. There is also a &lt;a class=&#34;link&#34; href=&#34;https://github.com/CaiJimmy/hugo-theme-stack-starter&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub template&lt;/a&gt; available which allows you to quickly setup your own blog based on this theme.&lt;/p&gt;
&lt;p&gt;Not a lot to say about this part, except that I encourage you to have a look at the &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/hugo-modules/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo Modules&lt;/a&gt;, which will save you from having to deal with submodules (and will make it easier when you need to update your theme).&lt;/p&gt;
&lt;h1 id=&#34;potential-improvements&#34;&gt;&lt;a href=&#34;#potential-improvements&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Potential Improvements
&lt;/h1&gt;&lt;p&gt;While I&amp;rsquo;m extremely satisfied with the end results, I noted a few points that could be improved in the future.&lt;/p&gt;
&lt;p&gt;First off, I saw that Hugo has a &lt;code&gt;deploy&lt;/code&gt; command that could, well, deploy your blog directly to an S3 bucket. Perfect! So I need to learn a bit more about &lt;a class=&#34;link&#34; href=&#34;https://gohugo.io/hosting-and-deployment/hugo-deploy/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Hugo Deploy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, even though using AWS as my hosting platform is not expensive (less than 2$ a month), it is not free. But it would be completely possible to use &lt;a class=&#34;link&#34; href=&#34;https://pages.github.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub Pages&lt;/a&gt; to make this blog accessible, while taking the advantage of GitHub as the hosting platform (on this point, I&amp;rsquo;m a bit reluctant, as then I would not be able to show-off with my beautifully made AWS diagrams&amp;hellip;).&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;&lt;a href=&#34;#conclusion&#34; class=&#34;header-anchor&#34;&gt;&lt;/a&gt;Conclusion
&lt;/h1&gt;&lt;p&gt;Here we are, you know everything!&lt;/p&gt;
&lt;p&gt;From my beginnings with WordPress, which, while being useful, showed some weaknesses on the backup, maintainability and deployment part.&lt;/p&gt;
&lt;p&gt;Of my research to find the perfect technical suite: AWS, Terraform, Hugo and GitHub Actions, all of that to enable a speedy deployment at almost no cost!&lt;/p&gt;
&lt;p&gt;When I look back to my previous setup and compare to what I have today, I am so happy to have done the switch!&lt;/p&gt;
&lt;p&gt;Now, it&amp;rsquo;s up to you! You have all the information to create your own blog and deploy all of this with a breeze!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Happy blogging !&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://antoinedelia.github.io/cloud-optimist/pr-144/img/how-i-automated-my-blog-to-the-cloud/happy_blog.jpeg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Successfully migrated my blog to the Cloud&#34;
	
	
&gt;&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
