<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Luca</title>
    <description>The latest articles on Forem by Luca (@luca29373).</description>
    <link>https://forem.com/luca29373</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3828946%2F0cfaf249-d0cf-48fe-8d66-25cdc86cdc1e.png</url>
      <title>Forem: Luca</title>
      <link>https://forem.com/luca29373</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/luca29373"/>
    <language>en</language>
    <item>
      <title>Our Terraform Drift Went Undetected for Four Months. Here Is How We Found It.</title>
      <dc:creator>Luca</dc:creator>
      <pubDate>Sat, 18 Apr 2026 16:16:52 +0000</pubDate>
      <link>https://forem.com/luca29373/our-terraform-drift-went-undetected-for-four-months-here-is-how-we-found-it-2ana</link>
      <guid>https://forem.com/luca29373/our-terraform-drift-went-undetected-for-four-months-here-is-how-we-found-it-2ana</guid>
      <description>&lt;p&gt;In my last post I talked about state file corruption and the mess that comes with it. This one is about a quieter problem that lived alongside it for months without us noticing. Infrastructure drift.&lt;/p&gt;

&lt;p&gt;Drift is what happens when the actual state of your cloud resources stops matching what your Terraform code says they should be. It can happen for obvious reasons like a developer tweaking a security group rule in the console during an incident. But it can also accumulate slowly and invisibly over weeks through automated processes, manual patches, and one-off fixes that never made it back into code. That second kind is what got us.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Started
&lt;/h2&gt;

&lt;p&gt;We had been running a mix of production and staging workloads across three AWS accounts since early 2024. Our Terraform setup was the standard arrangement: S3 remote state, DynamoDB locking, workspaces for environment separation. The team was disciplined about infrastructure changes for the most part. PRs went through review, applies were done through the pipeline, and we had a rule that console changes were for emergencies only.&lt;/p&gt;

&lt;p&gt;The rule held about 80% of the time. The other 20% was what caused the problem.&lt;/p&gt;

&lt;p&gt;During incidents people make console changes because it is faster than writing Terraform, opening a PR and waiting for a pipeline. A security group rule gets widened to unblock something at 11pm. An EC2 instance gets a tag added so billing can track a cost spike. A CloudWatch alarm threshold gets bumped because it was firing too often. None of these feel significant in the moment. None of them get turned into Terraform code afterwards because the incident is over and there are other things to do.&lt;/p&gt;

&lt;p&gt;Over four months that 20% added up to 47 individual resources across our three AWS accounts that had diverged from what our Terraform code described. We didn't know this until a routine audit in January 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  How We Found It
&lt;/h2&gt;

&lt;p&gt;We found it by accident. We were running a terraform plan on our staging environment to test a new module we were writing. The plan came back with a wall of changes that had nothing to do with the module we were adding. Resources we hadn't touched in months were showing up as needing modifications. Some showed diffs on fields we didn't recognise changing. One showed a resource that Terraform thought existed but was actually gone.&lt;/p&gt;

&lt;p&gt;We ran terraform plan across our other workspaces and found the same pattern everywhere. The cumulative drift from four months of incident-time console changes was sitting there waiting for the next apply to either overwrite it or explode trying.&lt;/p&gt;

&lt;p&gt;The dangerous part was not the drift itself. It was the fact that some of the drifted state was intentional. The security group rule that was widened during that 11pm incident had stayed widened because widening it had actually fixed the underlying problem. If we had blindly run terraform apply it would have put that rule back to its original tighter setting and broken production again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Did to Untangle It
&lt;/h2&gt;

&lt;p&gt;Reconciling four months of drift manually was unpleasant. We went resource by resource through the plan output and for each differing resource asked two questions. Is the current live state correct or is the Terraform code correct? Who changed it and when?&lt;/p&gt;

&lt;p&gt;For about 60% of the drifted resources the live state was correct and the Terraform code needed updating to match it. For 30% the Terraform code was correct and the live change was genuinely stale and could be overwritten. For the remaining 10% we genuinely couldn't tell and had to track down the people involved to get context.&lt;/p&gt;

&lt;p&gt;The reconciliation took three engineers two full days. At the end of it we ran a clean plan across all environments and saw no unexpected changes for the first time in months.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Put In Place After
&lt;/h2&gt;

&lt;p&gt;We came out of this with three changes that have stuck.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drift detection on a schedule&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We set up a GitHub Actions workflow that runs terraform plan in read-only mode across all our workspaces every night and posts a summary to a Slack channel. If the plan is clean it posts a green check. If there are unexpected diffs it posts a list of the affected resources.&lt;/p&gt;

&lt;p&gt;The first week it ran we caught two new drifts within 24 hours of them happening instead of four months later. The feedback loop being that tight changes how people think about console changes because they know it'll show up in Slack the next morning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Drift Detection&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;detect-drift&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Terraform&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hashicorp/setup-terraform@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Plan&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;terraform init&lt;/span&gt;
          &lt;span class="s"&gt;terraform plan -detailed-exitcode 2&amp;gt;&amp;amp;1 | tee plan-output.txt&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Notify Slack&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;failure()&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;slackapi/slack-github-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;{"text": "Terraform drift detected in ${{ github.workflow }}. Check the Actions run for details."}&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SLACK_WEBHOOK_URL }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;A proper incident infrastructure runbook&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The root cause of most of our drift was that engineers had no fast legitimate path for making temporary infrastructure changes during incidents. Console was faster than Terraform so console won.&lt;/p&gt;

&lt;p&gt;We wrote a short runbook for incident-time infrastructure changes. The runbook says: if you make a console change during an incident you open a follow-up ticket before the incident is closed, and that ticket must include a Terraform PR to codify the change within 48 hours. The on-call engineer who closes the incident is responsible for making sure the ticket exists.&lt;/p&gt;

&lt;p&gt;It is not a technical solution. It is a process one. But it has worked better than we expected because it does not add friction to the incident itself, it just requires a small step at close-out when the pressure is off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tagging console-created resources&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We turned on an AWS Config rule that flags any resource created without a specific terraform-managed tag. Resources created through our pipelines get the tag automatically. Resources created through the console do not. This gives us a live view in Config of anything in our accounts that has no corresponding Terraform management.&lt;/p&gt;

&lt;p&gt;It does not prevent console changes but it makes them visible immediately rather than discoverable only when someone runs a plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where We Are Now
&lt;/h2&gt;

&lt;p&gt;Four months after putting these in place we have had zero multi-week drift go undetected. The nightly plan check has caught eight individual drifts. Six of those were small tag changes. One was a security group modification. One was a manually created S3 bucket that a developer had spun up to test something and forgotten about.&lt;/p&gt;

&lt;p&gt;None of them had time to compound into the four-month backlog we had to deal with in January.&lt;/p&gt;

&lt;p&gt;The honest truth is that drift is not a Terraform problem. It is a team behaviour problem that Terraform exposes. The technical tooling helps but what actually fixed it for us was making drift visible quickly enough that it stayed a small problem instead of growing into a large one.&lt;/p&gt;

&lt;p&gt;If you are not running regular plan checks in your environments you are almost certainly accumulating drift right now. The question is just whether you will find it in days or months.&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
      <category>devops</category>
      <category>infrastructureascode</category>
    </item>
    <item>
      <title>How MechCloud Changed the Way We Manage Cloud Infrastructure at Our Startup</title>
      <dc:creator>Luca</dc:creator>
      <pubDate>Tue, 17 Mar 2026 17:14:12 +0000</pubDate>
      <link>https://forem.com/luca29373/how-mechcloud-changed-the-way-we-manage-cloud-infrastructure-at-our-startup-39ba</link>
      <guid>https://forem.com/luca29373/how-mechcloud-changed-the-way-we-manage-cloud-infrastructure-at-our-startup-39ba</guid>
      <description>&lt;p&gt;I've been working as a DevOps engineer at a fast-growing startup for just over two years now. Like many engineers in my position, I inherited a Terraform-heavy setup - S3 backends, DynamoDB state locking, remote workspaces, the whole nine yards. For a while, it worked. Then it didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State File Problem Was Real
&lt;/h2&gt;

&lt;p&gt;Our team had grown from 3 to 12 engineers over 18 months. With more people touching infrastructure simultaneously, we started hitting a wall of issues that are all too familiar in the DevOps world: corrupted state files, state lock contention, and the dreaded "state drift" where what Terraform thinks exists and what actually exists in AWS start diverging.&lt;/p&gt;

&lt;p&gt;One particularly bad week, two of our engineers were running terraform apply at the same time on overlapping modules. The state lock failed to engage properly, the state file got corrupted, and we spent an entire afternoon manually reconciling what was supposed to be deployed versus what was actually running. That was the moment I started seriously looking for alternatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter MechCloud
&lt;/h2&gt;

&lt;p&gt;A colleague mentioned &lt;a href="https://mechcloud.io" rel="noopener noreferrer"&gt;MechCloud&lt;/a&gt; in our DevOps Slack channel. The pitch was simple but bold: a platform that lets you provision and manage cloud infrastructure without ever touching a state file. I was skeptical at first. IaC without state files? How does it know what's already deployed?&lt;/p&gt;

&lt;p&gt;The answer, it turns out, is elegant: MechCloud treats the live cloud environment itself as the single source of truth. Instead of reconciling against a stored state file, it queries your actual cloud accounts in real time. No state, no drift, no locking issues by design.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Stateless IaC Actually Means in Practice
&lt;/h2&gt;

&lt;p&gt;MechCloud uses YAML-based blueprints to define your desired infrastructure state. You write what you want, and MechCloud figures out how to get there by comparing your definition against what's actually running in your cloud account. In practice, a few things stood out right away:&lt;/p&gt;

&lt;p&gt;No backend setup: no S3 bucket, no DynamoDB table, no remote workspace configuration to wrangle. Connecting our AWS account took minutes.&lt;br&gt;
No state drift: because MechCloud reads your live cloud on every operation, it always reflects reality. If someone manually changed a security group rule in the console, MechCloud sees it immediately.&lt;br&gt;
Parallel deployments: multiple engineers can deploy simultaneously to different parts of the infrastructure without worrying about locking each other out.&lt;br&gt;
No import headaches: existing infrastructure doesn't need to be imported before you can manage it, which made onboarding our existing AWS resources much less painful than I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-Time Pricing - Surprisingly Useful
&lt;/h2&gt;

&lt;p&gt;One feature I didn't expect to care about was real-time pricing. As you design your infrastructure in MechCloud, it shows you live pricing from the cloud providers right alongside your resources. Before you provision an EC2 instance, you can see exactly what it'll cost per hour and per month.&lt;/p&gt;

&lt;p&gt;We've caught a few over-provisioning mistakes at the design stage this way - instances that were sized higher than they needed to be. It's not a feature I'd have thought to ask for, but now that I've used it I'd find it hard to go back to designing infrastructure blind on cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep AWS Integration Out of the Box
&lt;/h2&gt;

&lt;p&gt;We're a pure AWS shop, and MechCloud fits well into our workflow. Connecting our AWS accounts was straightforward, and the platform gave us immediate visibility into our entire AWS footprint from a single interface. The visualization layer in particular has made architecture review conversations a lot easier - having an interactive diagram of your live infrastructure is something I didn't realize I was missing until it was in front of me.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Agents: The Unexpected Bonus
&lt;/h2&gt;

&lt;p&gt;I wasn't expecting to use MechCloud's AI agent capabilities much - I figured it was a nice-to-have. But during a late-night incident when I needed to quickly query the state of EC2 instances across multiple accounts, I typed a plain English question into the AWS Agent and got back exactly what I needed in seconds.&lt;/p&gt;

&lt;p&gt;It runs entirely in the cloud with no local setup and no API keys stored anywhere on our end. For quick incident queries it's saved me a fair bit of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does It Replace Terraform Entirely?
&lt;/h2&gt;

&lt;p&gt;Not yet, at least not for us. We're still running Terraform for some production workloads, and we've been testing MechCloud on our dev and QA instances since January 2026. The experience so far has been solid - faster deployments, zero state-related headaches, and the real-time pricing has already paid for itself in avoided over-provisioning. We're cautiously moving toward expanding its use, but I wouldn't want to overstate where we are.&lt;/p&gt;

&lt;p&gt;What I can say is that for AWS-focused teams, MechCloud covers the core infrastructure work well - VPCs, subnets, EC2, S3, RDS, EKS. If your pain is mostly state management and you're all-in on AWS, it's genuinely worth evaluating.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Verdict
&lt;/h2&gt;

&lt;p&gt;If you're an AWS-focused DevOps engineer who's spent too many hours dealing with state file corruption, lock contention, or drift - MechCloud is worth a look. It's not a silver bullet, and we haven't fully replaced Terraform with it yet, but the stateless approach does solve real problems in a way that actually holds up day-to-day.&lt;br&gt;
The pricing is reasonable for what you get, and the free tier is usable enough to form a real opinion before committing. I'm cautiously optimistic about where we'll be with it six months from now.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>infrastructureascode</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
