Agentic coding lets me move very fast. A feature gets built in days. A design gets implemented in a matter of hours. Changing a layout, updating a template, reworking a flow: all of it happens at a speed I couldn’t have imagined a year ago.
There’s one part of the stack where none of that speed applies to me: the data.
Everything else has an undo button#
Most of my work these days happens from a phone, talking to a remote coding environment . A lot of that work is iteration, and iteration is cheap when a change can be reverted.
- A layout that doesn’t quite work once people use it? The next version is a deploy away.
- A bug? Fixed, deployed, gone.
- Some translations that are wrong? Redeploy, fixed.
- A redesign that makes part of the UI less confusing, but harder to use? Redeploy, fixed.
- Started a feature and don’t like where it’s going? Cancel it. The branch just sits there, harmless.
None of that goes out untested. Every change still runs through the test suite, and I still read the diff before it merges. What changed is the cost of a wrong call: if a screen turns out to be confusing once real people use it, the fix is minutes away. That’s why I’m comfortable doing that kind of work from the couch.
So I move quickly, iterate, pivot, change my mind halfway through, deploy and redeploy, undo things I didn’t even finish, … It’s the reason I take more time to think about features now: generating a new version is so cheap that trying three of them is the normal way to work.
Data doesn’t#
Every time I have to touch the data layer, I stop.
I can’t do it from a phone. I need to be behind a desk, at a laptop, in thinking mode, without distractions. Because this is the layer where a mistake doesn’t get undone by the next deploy.
There are coding patterns that soften the blow, sure. Soft deletes, a migration with a proper down(), a backup from last night. But those undo a change to the code, not the loss itself. If a migration truncated a column, the down() puts the column back. Empty.
Event sourcing
gets the closest. You don’t store the current state, you store every change as an event (OrderPlaced, AddressChanged, …) and build your tables from those. Break a table with a bad migration? Throw it away and replay the events into a new one. Spatie’s event sourcing package
has an event-sourcing:replay command for that. That’s a real undo button for the data layer.
But the one-way door is still there, it just moved to the events. The log is append-only, so a badly designed event stays in it forever. An event you never recorded can’t be replayed. And an append-only log of everything a user ever did is the last thing you want when that user asks you to delete their account.
Data is data. If you don’t have it, you can’t reproduce it.
Take Snapkin . When you tell it once that the white blob on your breakfast plate is skyr and not yogurt, it remembers that and uses it from then on. I can rebuild the screen that asked the question in an afternoon. I can’t rebuild the answer. Only the person who ate the skyr knows that, and they told the app exactly once.
One-way doors#
Jeff Bezos has a name for this. In his 2015 letter to Amazon shareholders , he splits decisions into two kinds:
Some decisions are consequential and irreversible or nearly irreversible – one-way doors – and these decisions must be made methodically, carefully, slowly, with great deliberation and consultation. If you walk through and don’t like what you see on the other side, you can’t get back to where you were before. […] But most decisions aren’t like that – they are changeable, reversible – they’re two-way doors.
Agentic coding turned almost everything I build into a two-way door. A layout, a feature, a translation: walk through, don’t like it, walk back.
Bezos was warning about treating two-way doors with one-way care, because that makes a company slow. With agents, I worry about the opposite mistake: walking through a one-way door at two-way-door speed, because everything around it moves that fast.
And the data layer is where the one-way doors are:
- Migrations.
- What you store, and in which format.
- Data structures.
- Backups.
- Recovery.
Every data migration, and every moment in the app where I have to decide whether to store something and if so, how, makes me take a break. Those decisions are where most of my time and thinking goes now. Not the UI, not the UX, not the features, not what’s next on the list. All of those can stay fluid. They change, and I adapt them to what users say or want.
The data is sacred.
That doesn’t make a data decision permanent. I can change a column type, split a table or move a field somewhere else later. But every one of those changes touches rows that already exist, so it takes a lot more effort and thinking to make sure nothing gets lost and that every change to the data is intentional. A layout change is a new deploy. A data change is a plan: what happens to every existing row, how I check it worked, and how I get back if it didn’t.
A field I decide to store is a field I now have to protect, back up, and eventually delete again. A field I decide not to store is gone for good. I can’t go back and ask people what they did last Tuesday.
Privacy and retention don’t get rushed either#
Then there’s privacy and data retention. How long do I keep something? Who can see it? What happens when somebody deletes their account, and does that also cover the backups? What does a backup even mean if it holds data I promised to throw away?
None of those have a quick answer, and none of them get easier because an agent can write the migration in 30 seconds. Writing the migration was never the slow part. Thinking through what it does to data that’s already there is.
The data is the application#
Take everything away from an app: the UI, the website, the mobile app, the servers, the infrastructure. You can build all of that again, and with the tools we have now, faster than ever.
You can’t do that with the data your users gave you. Lose it, and whatever you rebuild is an empty shell with a login screen.
So I’ll happily iterate on a layout from my phone. The migration waits until I’m at my desk.