In 2026 anyone can build an app in a weekend. AI writes the code. Building is not the hard part anymore.
The hard part is thinking about what happens after.
I want to show you what that actually looks like, using a small feature I shipped last month. Not a big architectural thing. A backup button. It took a few minutes to write and most of a day to make safe, and the gap between those two numbers is the whole point of this post.
A little background
I build AxioDB, a small database for Node.js apps.
Normally, when your app needs a database, you install a separate one and keep it running. That is fine for a web service. It is annoying for a desktop app, a CLI tool, or a side project you want someone to be able to just run. AxioDB skips that step. You run npm install, and you have a database.
It stores everything as plain folders on disk. One main folder, your databases inside it, and each database holds its collections. Inside a collection sit the actual records, plus a hash index.
If "hash index" sounds heavier than it is: it is a lookup table. Instead of reading every record to find one, it takes the ID and jumps straight to it. One step, no matter how many records are in there. The values are kept sorted as well, so a query like "everything between these two dates" stays fast instead of turning into a full scan.
The feature
Export and import.
Export zips that whole folder into a single file. Records, hash index, all of it. You hand that file to a different machine running AxioDB, import it there, and the database comes up ready to query. Nothing gets rebuilt, because nothing needs to be. The index travelled with the data.
That is genuinely useful. Move your data between machines, keep a backup, hand a working database to a teammate.
And writing it was quick. Zip a folder. Unzip a folder. You could do it in an afternoon.
Then you sit with it for a minute and three questions show up.
Question 1: what if the uploaded file is not really a backup?
There is an old trick where a file is only 1 MB, and the moment you start unpacking it, it becomes 10 GB. It is small because it is mostly the same byte repeated, and compression is very good at that. Your disk fills up and your app stops.
My first idea was to block anything above 512 MB.
That does nothing.
Think about it for a second. The bad file is already small. It sails through a size check without noticing it exists. Meanwhile the check happily blocks a real user who has a genuinely large database and just wants their data back.
So the size limit fails in both directions at once. It does not stop what it was meant to stop, and it stops something it was never meant to stop.
Size was the wrong thing to watch. Growth was the right one.
What it does now is measure while unpacking. It watches how much goes in against how much comes out. If 8 MB is turning into 800 MB, that is not a database, and it stops right there and deletes what it has written so far.
A real backup compresses. It does not multiply.
I tested it against an actual one of these files, the kind that grows about a thousand times over. It stopped in time.
The lesson I keep taking from this one: when a guard feels obvious, check whether it is measuring the thing you are actually afraid of, or just the nearest number you could reach.
Question 2: what if two people restore at the same time?
Two people, two uploads, same server, same moment.
What should happen depends on what they are uploading. Two different databases, both should go through, they have nothing to do with each other. The same database twice, one should win and the other should be told clearly, because otherwise they are both writing to the same folder and you get a mess neither of them asked for.
So you need to know whether two uploads are "the same".
The easy answer is to compare file names.
The easy answer is wrong twice over.
Names lie in both directions. The same backup can be saved under two different names, so you would let both through and let them collide. And two completely unrelated databases can both be sitting there called backup.tar.gz, so you would block one for no reason at all.
A file name is a label someone typed. It is not identity.
So the import opens the file first and reads the real database name from inside it, and locks on that. Different databases, both proceed. Same database, the second person gets a clear message telling them it is already being imported, instead of silently landing on top of the first one.
Same idea as the first question, honestly. The obvious thing to measure was not the thing that mattered.
Question 3: what if it fails halfway?
This one is less clever and more important.
An import used to unpack straight into the live folder. Which means if the file broke halfway through, or one of the checks above fired mid-unpack, you were left with half a database. Real data, partly overwritten, partly not. That is worse than a failed import. That is a failed import that took your data with it.
So now it runs in three steps. Stage, validate, promote.
Stage. The upload goes into a temporary folder outside your data directory and gets unpacked there. Your real database has not been touched yet and does not know any of this is happening.
Validate. Everything gets checked in that temporary folder. Is this actually an AxioDB export? Are the folders shaped the way they should be? Is anything trying to write outside where it belongs? All of this runs off to the side, where nothing it does can hurt anything real.
Promote. Only once every check has passed does it move into the real place, in a single move.
If anything fails at any point, the temporary folder is deleted and your live data was never opened at all. There is no half state to recover from, because the live folder only ever sees a database that already passed.
The part I actually want you to take away
None of these fixes are big. The whole thing is maybe a hundred lines. AI could have written every one of them for me in a couple of minutes, and honestly, it wrote a fair bit of the surrounding code.
But it writes exactly what you ask for.
It did not ask me what happens when the file is fake. It did not ask what happens when two people click at the same time. It did not ask what is left on disk when something breaks in the middle.
Those three questions are what turned a working feature into a safe one, and they came from sitting with the thing rather than from typing faster.
Building is cheap now. That is great, genuinely. It just means the value moved somewhere else, and it moved to the part where you look at what you built and ask what it does on its worst day.
That part is still ours.
AxioDB is open source. If you want to poke at any of this, it is on GitHub and on npm.