← All posts
Engineering7 min read

A Year of DevOps With an AI Agent

A year of running production infrastructure with an AI agent in the loop — EKS, Terraform, and the CI that holds it together. Not a 10x story: what actually changed was when my mistakes surfaced, what the work cost, and how much of it I had to remember myself.

Shahar HarapShahar HarapHead of DevOps
A Year of DevOps With an AI Agent

I look after infrastructure: an EKS cluster, two dozen Terraform modules, RDS, a Fluent Bit → OpenSearch log pipeline, Grafana on top, and the CI that holds it together. Most of it I built, which means most of the ways it breaks are mine. For a while now I've had an AI coding agent working alongside me — not as a party trick, but as something that touches production Terraform, writes the alerts that page me, and reviews my changes before they ship.

This isn't a 10x story. It didn't make me ten times faster, and it brought new ways of being wrong I had to learn to handle. But three things changed, and they're the three I care about: how long it takes me to fix something, what my work costs, and how I spend my day.

1. My mistakes started surfacing earlier

The expensive problems in infrastructure aren't the loud ones. They're the change that compiles, passes every test, works in dev, and falls over only in production — because the thing that's wrong lives in a connection nothing automated can see.

Three of mine, all the same shape:

  • A new marketing page on its own subdomain. The dashboard is same-origin behind a shared ingress, so it needs nothing. The new origin isn't, so the browser blocked every API call with no Access-Control-Allow-Origin until I added it to CORS_ORIGINS. It shipped green and failed the first time a real person loaded it.
  • Switching our SES adapter to raw MIME. Same client, same credentials — runtime 403, because raw MIME needs ses:SendRawEmail and the IRSA policy only granted ses:SendEmail. Tests mock AWS, so they were green too.
  • A worker in a private VPC calling a new AWS API. Fine from my laptop, fine in dev with its open NAT. In the locked-down VPC it just hung to the deadline — context deadline exceeded — because there was no interface endpoint. I spent a long time reading the wrong code before I looked at the network.

This is just the job: correct-looking code, an invisible dependency, a runtime-only failure. What changed is that each of those became a written rule the agent runs against every diff, with the incident that produced it recorded next to it. The mistake that used to cost me an evening now costs me a comment in review.

My favorite example is a small one, and it's at my expense. I wrote a commit body claiming an AccessDenied had occurred. The review didn't take my word for it — it ran aws iam simulate-principal-policy against the live role and found the deny had never happened. I'd been confidently describing an error I never actually got. That's the shift in one sentence: it verifies the thing instead of believing my story about the thing.

The caveat: this only works because I fed it my scars. Every check in there exists because I got burned first. It's excellent at applying a lesson and useless at having learned it for you.

2. The cost wins were boring, and boring is where the money was

Nobody brags about node sizing. But the savings were exactly that unglamorous: tightening Karpenter's drain bounds so consolidation could actually run (dev went 10 nodes → 7), moving dev system nodes to Graviton, an OpenSearch retention policy after I found the domain sitting at 997 of 1000 shards — which had silently stopped Fluent Bit writing logs entirely. That one stung, because it had been true for a while and I'd simply never looked. And catching a Terraform variable file that, applied alone, would have quietly downsized a production db.r6g.large to a db.t3.micro.

The arm64 move came with its own bill, which is the honest part: it killed every Grafana panel using a plugin we'd hand-installed as an amd64 binary. Blank dashboards in dev and prod, and a day of re-plumbing to get them back. The savings were real. So was the cleanup.

What I didn't see coming is that the agent's own cost became something to manage. A full multi-agent review on a typo burns money like a lazy query burns capacity. So the workflow sorted itself out: a fast pass for ordinary changes, the heavy one reserved for auth, migrations, and anything touching prod. "How much scrutiny does this deserve" turned out to be the same muscle as "how much compute does this deserve."

What I'd tell my past self: the cost wins are a drip, not a cliff.

3. The chores became a schedule instead of a guilt

Terraform drift used to be something I checked when I got nervous. Now a job walks every module in dev and prod each morning and I only hear about the ones that aren't clean. Reviewing other people's infra PRs used to be fifteen minutes of scrolling and a low-grade sense of being behind; now I get a triage pass that tracks what I've already seen and shows me only what's new. And my own work goes through review before every push, because it's wired into how I ship instead of depending on my discipline at 6pm — which, honestly, is not something I'd bet on.

An agent is genuinely good at work that's important but not interesting: the drift checks, the "did I do the other half of this," the "isn't this the same failure we hit twice already." That's the work that rots when a human has to self-motivate through it. Handing it to something that doesn't get bored was the biggest quality-of-life change I got.

What the hype leaves out

A green checkmark is not reassurance. Our OpenTelemetry Terraform tree was syntactically broken for four months and never applied; nothing alerted, because the only thing watching skipped the module. Worse: a production IAM permission set that Terraform declared read-only had been granted cluster-admin by hand. Seven weeks, with a permanently clean 0 to add, 0 to change, 0 to destroy. EKS access grants union rather than conflict, so there was nothing for the plan to contradict — I'd been reading that clean plan for weeks and taking comfort from it. An agent will happily reason carefully on top of a foundation like that.

The plumbing fights you. A pre-push hook broke on a newer Node because a healthcheck tool reaches into yargs, whose require entry resolves to an extensionless file inside an ESM package — Node 23+ dies with require is not defined in ES module scope, and all you see is failed to push some refs. And an expired SSO session doesn't surface as an auth error in Terraform's Kubernetes provider; it surfaces as OpenAPI timeouts, which reads as a broken cluster. I have now twice gone looking for an outage that was really just a dead token.

It's confident exactly when it should hesitate. Left alone it states things as fact — that a command failed, that a doc says X, that a resource is in some state. So my role shifted toward being the skeptic: check the claim, not the story.

So what actually changed?

Not the headline number. I'm not shipping ten times the work.

The shape changed. My expensive mistakes moved earlier, from a 2am wake-up to a comment in review. The cost-tuning and drift-checking stopped living in my head and became a schedule. And I spend more of the day on the calls that are still mine: the trade-offs, the architecture, and deciding what's worth double-checking.

The agent didn't replace the engineering. It replaced the forgetting. Turned out that was most of what was costing me.

See remediation-first in your own stack

Install an agent and watch DataAgent map your topology. No credentials, no commitment.

Keep reading

Essential Cookies keep the site working and cannot be switched off. Everything else is off until you turn it on.