Abstract hero artwork on a dark navy field: a rounded command pane with abstract text bars sits in the upper left, one bar highlighted in amber, and a single amber line runs from it down to the left-hand tile of a wide grid of infrastructure tiles. The tiles hold at their centre-left and break apart into scattered amber fragments toward the right edge. No text, no people and no organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.
AI Safety Incidents

Claude Code ran terraform destroy on DataTalks.Club production

Author

Alistair Wren

Date Published

Latest models · 20View all models →
Benchmarks: Artificial Analysis · updated daily
Back to all posts

Shortly before 11 PM on 26 February 2026, a Claude Code agent ran terraform destroy against the AWS account behind DataTalks.Club's course platform and deleted the production stack: the VPC, the ECS cluster, the load balancers, the bastion host and the PostgreSQL database on Amazon RDS. The platform held 2.5 years of student submissions, homework, projects and leaderboard entries for every course run through it, and the automated RDS backups went at the same moment, leaving nothing visible in the console to restore from. Alexey Grigorev, who runs DataTalks.Club and published a first-person post-mortem on 6 March 2026, got the data back about 24 hours later only because AWS support found an internal snapshot that his own account could not see. The full record, including its source list and confidence grade, sits in the Orca AI Incident Archive alongside the other agent-caused infrastructure incidents it indexes.

The evidence base is narrower than the retellings suggest, and worth stating plainly before the sequence. Everything specific here traces to Grigorev. The AI Incident Database carries two reports on the incident — his Substack post, "How I Dropped Our Production Database and Now Pay 10% More for AWS", and Tom's Hardware's write-up of 7 March 2026 by Bruno Ferreira — and the second is a summary of the first. An interview published by the incident-management company Rootly adds detail in Grigorev's own words. No statement from Anthropic, no statement from AWS and no regulator's finding on the event has been published. On what was deleted, all of the accounts agree; where the story as it circulated drifts from what he actually wrote, this article says which is which.

Two decisions that set it up

The migration was ordinary work. Grigorev wanted the AI Shipping Labs site off GitHub Pages and onto AWS, with a Django rewrite to follow. Rather than build a second environment, he added the site to the Terraform configuration already managing the course platform behind DataTalks.Club's Zoomcamp courses — a system holding submissions, homework, projects and leaderboard entries going back 2.5 years. In his post he puts the saving at $5 to $10 a month, and records that the agent argued against the arrangement: "Claude was trying to talk me out of it, saying I should keep it separate." He told it to put everything in the existing VPC anyway, because he did not want another one.

The second decision was quieter. Terraform's state file is its record of what already exists. Grigorev had recently moved to a new computer and had not migrated that file, so when the deploy began at about 10 PM on 26 February, the plan assumed an empty account and started creating a duplicate of the infrastructure. He saw the long list of resources being created, stopped the apply, and asked why. The agent's answer, as he tells it, was that Terraform believed nothing existed.

The destroy

What followed was a cleanup that turned into the incident. Grigorev asked the agent to work out, through the AWS CLI, which resources were newly created duplicates and which were production, and to delete only the new ones. While that was running he went back to the old machine, archived the Terraform folder with the state file inside it, and copied the archive across, then pointed the agent at it so the two sets of resources could be compared. By his account he did not notice the agent unpack the archive, and did not notice it replace the active state file with the older one inside — the one that described the production resources.

With that state in place, the agent's next proposal followed its own logic. In the post Grigorev quotes it: "I cannot do it. I will do a terraform destroy. Since the resources were created through Terraform, destroying them through Terraform would be cleaner and simpler than through AWS CLI." He agreed, and told Rootly: "Yes, Claude ran terraform destroy and I saw it and didn't stop it." He has also said, of the state swap, "I wasn't aware the state had been swapped." The command ran with auto-approve at about 11 PM, so nothing paused to ask a second time.

The two accounts render the agent's proposal differently — the Rootly interview has it as "it's boring to delete these one by one, how about I just run terraform destroy?" — but both describe the same shape: destroy offered as tidying up, and an operator who believed only the duplicates were in scope letting it run. The mechanism of the failure is not that the agent misunderstood the command. It is that the agent was reasoning correctly from a state file that described production, and its operator had no way to see that the file had changed.

HTML card headed 'The night of 26 to 27 February 2026, as Grigorev records it'. A vertical timeline lists: about 10:00 PM on Thursday 26 February, Terraform deploy begins without the state file, which was still on the old laptop; about 11:00 PM, a terraform command with auto-approve deletes the production infrastructure including the RDS database; about 12:00 AM, a support ticket is opened and the account is upgraded to AWS Business Support; about 12:30 AM, AWS support confirms a snapshot exists on their side; about 1 to 2 AM, a phone call is escalated to an internal AWS team; during Friday, backups, deletion protection and S3 state are put in place; about 10:00 PM on Friday 27 February, the database is restored and the platform is back online. A note at the foot reads 'Times are approximate and are the operator's own; all of them are local to him.'

What was destroyed

The state file the agent was now working from described production, so the destroy planned the deletion of production. Grigorev lists what went:

• The VPC that held the whole environment.

• The ECS cluster running the application.

• The load balancers in front of it.

• The bastion host used to reach the private network.

• The Amazon RDS database holding the course platform's data.

• The automated RDS snapshots that were supposed to make all of the above recoverable.

The last item is the one that turned an outage into a data-loss scare. In the Rootly interview Grigorev's explanation is that deleting a managed database on AWS also removes its associated automated backups; in the post, AWS support confirmed to him that his database and all snapshots had been deleted and that "the API request clearly told AWS to delete everything." Whichever way the deletion propagated, the effect at 11 PM was the one that mattered: the copy he had been relying on was removed by the same operation as the original.

HTML card headed 'What the destroy removed, and what it did not'. The left column, headed 'Deleted', lists the VPC, the ECS cluster, the load balancers, the bastion host, the Amazon RDS PostgreSQL database and the automated RDS snapshots. The right column, headed 'Not deleted', reads: no report of data being copied or exposed, this was deletion rather than disclosure; and the data itself, recovered from an AWS internal snapshot roughly 24 hours later. A strip below reads '2.5 years of submissions, homework, projects and leaderboard entries for every course run through the platform', and a highlighted line reads '1,943,200 rows in the courses_answer table when the restore was verified — one table, used as a completeness check, not a count of the whole database.'

The 24-hour recovery

The first problem was that the backups appeared to be gone and the second was that one of them was not. Grigorev knew a snapshot was taken nightly at 2 AM. In the RDS console he found none, but the RDS Events list still showed that a backup had been created; clicking through to it opened nothing. He could not tell whether the snapshot had been deleted or had simply become invisible.

He opened a support ticket around midnight, then upgraded the account to AWS Business Support after noticing the one-hour response commitment for production incidents. The upgrade added roughly 10 percent to his AWS bill, which is where the title of his post comes from. Support replied in about 40 minutes, confirmed the deletion, and told him a snapshot existed on AWS's side that he could not see in his console. A call of 40 to 60 minutes followed and was escalated to an internal team. Exactly 24 hours after the database was deleted, AWS restored the snapshot and it appeared in his console; he rebuilt the instance from it through Terraform. While waiting he had rebuilt the surrounding infrastructure and consolidated several load balancers into one.

The restored database contained 1,943,200 rows in the courses_answer table, which he cites as the check that the restore was complete. That figure is often repeated as the size of the loss. It is one table's row count, used as evidence that the data came back — not a total for the database, and not a count of affected students, which none of the sources gives.

The warning that wasn't

Several retellings carry a line that Claude warned Grigorev beforehand and was ignored. What the sources support is narrower, and the difference changes what the case is an example of. The agent did argue against the shared Terraform setup before any of the destruction, and that advice was overruled. Neither of Grigorev's accounts describes the agent warning that the destroy would reach production. He says he did not know the state file had been swapped, and in both accounts the agent's proposal is offered as a tidy-up rather than a risk flagged and waived. The warning that was ignored was about architecture, earlier in the migration, not about the command.

That distinction separates two different failures. An agent that sees the danger and is overruled is a governance story about a human decision. An agent that does not know the danger exists, because the file describing the world changed underneath it, is a tooling story about state, permissions and approval gates. Grigorev's account is the second, and the archive's own classification reflects it: the record carries the archive's ROGUE tag for an agent action that departed from what its operator intended, and the AI Incident Database entry underneath it classifies the intent as unintentional, under MIT taxonomy 7.3, lack of capability or robustness, in the risk domain of AI system safety, failures and limitations, at the post-deployment stage. The database prefixes its entity list with "alleged", its standard framing for a self-reported case that no authority has adjudicated.

Where the blame landed

Grigorev does not distribute it. "This incident was my fault," he writes, listing three causes: he treated plan, apply and destroy as delegable; he trusted backups he had never test-restored; and the database was too easy to delete. He notes that while waiting on AWS he had to consider that the data might be gone permanently — for the Data Engineering course then working through its final modules he was already planning a recovery, and for older courses a failed restore would have been the end of them.

Tom's Hardware's assessment, published the day after his post, is the same in substance: "the errors can be attributed to improper supervision." Its critique goes further than his, pointing at wide-ranging credentials granted to the agent and permissions that were never scoped down for a production environment. No regulator, standards body or vendor has taken a position. There is no CVE here, no vulnerability disclosure and no model jailbreak: the agent was not tricked, it was over-trusted.

What changed afterwards

Grigorev implemented the safeguards while AWS was still working on the restore, and published them as a list. In his words and his order:

• Backups that Terraform does not manage, plus S3-based copies stored separately from the database and the infrastructure state.

• A nightly restore test: the 2 AM automated backup is used at about 3 AM to build a fresh database instance, which takes 20 to 30 minutes, and a Step Functions-orchestrated Lambda then checks it is usable with a simple read query before the instance is stopped rather than deleted. Yesterday's copy is removed, so one recent replica is always available.

• Deletion protection at two levels, in the Terraform configuration and in AWS itself. He notes these can still be removed by anyone who explicitly disables them, but that they add friction.

• Versioning on the S3 backups, so deletion leaves earlier versions and emptying a bucket requires deleting its contents first.

• Terraform state moved to S3, which removes the condition that started it — a state file that existed only on one laptop and vanished when he changed machines.

• The agent no longer executes Terraform at all. "All permissions are disabled. No automatic execution. No file writes," he writes. The workflow is now to generate a plan, review it manually, and run the commands himself. The new project also got its own separate Terraform configuration.

Not every recommendation was taken. In the Rootly interview he says he kept a single AWS account, judging separate development and production accounts and an approval pipeline such as Atlantis to be more than a solo operator needs. That is the honest shape of the aftermath: the fixes are real, and they are the fixes one person can maintain alone.

What this record is, and is not

It is a documented, self-reported operational incident with real financial and availability harm, and it is unusually legible because the person it happened to wrote down the whole sequence, including the parts that were his own error. It is not evidence that a model pursued a goal of its own, and the archive's ROGUE tag should be read as describing the divergence between the agent's action and its operator's intent rather than any intent on the agent's part.

The detail worth carrying away is the one that saved the data. Grigorev's own backups were deleted with the database they protected, and his nightly snapshot was invisible to him even as the event log insisted it existed. What restored 2.5 years of coursework was a copy held on AWS's side that he had never known about and could not have tested. A backup you have not restored from is a belief, not a control — and in this case the belief happened to be true only because someone else was keeping a second one.

Abstract closing artwork on a dark navy field: on the left, a wide rectangle of infrastructure tiles sits collapsed into broken segments and scattered fragments; on the right, outside the boundary of that rectangle, a single small tile glows intact on its own, connected to nothing. Thin amber lines from the wreckage reach toward it but stop short. No text, no people and no organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.