A few months ago I wrote that a database does three things. It executes queries. It manages relationships. It survives the physical machine it runs on. Everything else, every config parameter, every architecture decision, every incident anyone has ever fought, falls into one of those three categories. I called them the three promises, and the post was a diagnostic framework for DBAs. A way to locate a problem before you start solving it.

I wrote that post before the conversation about agents operating against production databases became urgent. Replit had wiped a database in July of last year. AWS Kiro had been blamed for an outage in February. Google Antigravity had erased a developer’s D drive in December. I had read all of them. None of it had yet pushed me to revisit the framework.

What pushed me was Arpit Bhayani’s piece on defensive databases, published a few weeks ago. His diagnosis is right and worth quoting: databases were designed assuming a deterministic, human-authored, reviewed-before-deploy caller, and agents violate every one of those assumptions. He prescribes defensive patterns at the application and schema layer. Soft deletes. deleted_by columns. Append-only event tables. Idempotency keys. Roles per agent type with least privilege.

His prescriptions are correct. They are also, for most production teams, a multi-quarter refactor that will not happen this year. The teams that need defense the most are the ones least able to rebuild their schema layer to get it.

That gap is what I want to close. Not by disagreeing with Arpit, but by pulling the conversation up one level. Before we talk about which patterns to apply, we have to ask which promises break and how. The patterns are the answers. The framework tells you which questions to ask.

What the framework actually does

The three promises were never a checklist. They were a diagnostic lens.

Replica falling behind? Three possible zip codes. Execute Queries: the primary is running queries so heavy that the replica can’t replay them fast enough. Relationships: the network between primary and replica can’t carry the replication stream. Survive: the replica’s disk I/O is saturated. Same symptom, three different drawers to open first.

The value of the lens is that it narrows the search before you start spending hours. If you go straight to tuning queries when the real problem is disk throughput on the replica, you waste the day.

The same lens, pointed at agentic failures, narrows the search just as well. The patterns Arpit prescribes don’t all live in the same place. Soft deletes are about Execute Queries, the contract about what a DELETE statement means. Roles per agent type are about Relationships, who gets in and what they can touch. Append-only event logs are about Survive, the ability to reconstruct state when something has already gone wrong. Three different promises, three different defenses. Pretending they’re the same kind of fix is part of why teams stall on implementing them.

What changes when the caller is not human

The promises don’t disappear in the agent era. The database has the same job. What changes is who is on the other side of the connection, and what assumptions about that caller were baked into how each promise gets fulfilled.

MySQL was designed for a caller that read the docs, reviewed the diff, and understood what they were doing before pressing enter. The schema’s foreign key constraint was a contract with a developer who had thought about referential integrity. The role’s privilege grants were a contract with a human user who had been onboarded with a security review. The binlog was for replication, with a mental model that whoever caused a write somewhere also caused the replica to catch up. None of these contracts were stupid. They were appropriate to the caller they assumed.

That caller is now sometimes an agent that took an inference shortcut, holds credentials it pulled from a config file it didn’t fully parse, and is operating on a goal that was specified in natural language by someone who is no longer in the loop. The contract didn’t break. The counterparty changed.

This is a more useful framing than “agents are dangerous” because it tells you exactly where to look. Each of the three promises has assumptions about the caller buried inside it. Find the assumptions, name them, and you have a list of the things that need to change.

A preview of where the assumptions live

I want to walk through each promise in detail, but not in a single post. The first and the third try cram into one piece would make this 5,000 words long and nobody would finish it. So this is the frame, and the next two posts go deeper.

Execute Queries assumes that the caller understands the tradeoffs of what they’re asking for. ACID still holds. Every individual query still runs correctly. What broke is the assumption that whoever issued the query had a model of why they wanted that exact query and what they’d give up if it succeeded. Disabling foreign_key_checks was always a tradeoff. The tradeoff is the same. The caller understanding it isn’t. Part 2 of this series is on this.

Relationships assumes a fixed taxonomy of counterparties. Users, peer databases, dev and ops teams. Three kinds of relationship, three kinds of audit and observability. The agent era introduces a fourth kind that doesn’t fit cleanly into any of those three. It’s tempting to call agents users-with-extra-suspicion. They’re not. They confess less, move faster, and leave less reconstructable context behind. They’re a different shape, and the relationship has to be designed for them explicitly. Part 3 of this series is on this. It’s the part of the framework where I think the industry has the least mature thinking and where my contribution is most original.

Survive assumes that survival is physical. Disk full, OOM, replication broken, backups that work. The agent era expands survival into a semantic layer. When an agent with valid credentials issues a syntactically and semantically valid DELETE against the wrong table, every physical metric stays green. The server survived. The data didn’t. There’s a fourth post for this, but it’s load-bearing for what I’m building right now and I want to give it more space than a series wrap-up. So I’ll come back to it on its own.

What this series is not

It is not a list of MySQL settings to flip. There will be specific recommendations as the posts go deeper, but if you came here looking for a checklist, the lens has to come first or the checklist is just cargo cult.

It is not a takedown of agents. I use them daily. They make me faster. The argument is not that they’re bad, it’s that the operational contract MySQL was designed around assumes a caller they don’t resemble, and the answer is to redesign the contract, not to ban the caller.

It is not a sales pitch. I’m building dbtrail with some of the brightest minds in the field and some of what falls out of this analysis is load-bearing for what we’re shipping. I’ll be explicit about that when it’s relevant. But the framework is the framework whether or not you ever look at our product.

What it is

It is an attempt to give people running MySQL in production a vocabulary for thinking about a problem that’s shifting under their feet faster than the trade press is keeping up with. Replit, Antigravity, Kiro, and the most recent incident are not isolated stories. They’re the same story told four times. The question isn’t whether more incidents are coming. They are. The question is whether the people operating MySQL in 2026 have a frame for predicting which kind of failure they’re about to see, and where the defense has to live.

The three promises are still the three promises. The job is to read them again, with new eyes, and figure out what each one demands when the caller is not human.

Part 2 is on the first promise. Coming next.

If you have an opinion on any of this, especially if it disagrees with mine, write. The frame is mine but the answers shouldn’t be one person’s job.


Daniel Guzmán Burgos. 20 years in MySQL, ex-Percona. Building dbtrail , continuous data protection for MySQL in the agent era.