"What if we switch to the app and something that the spreadsheet was quietly doing just... stops happening?"

A client said this to me almost verbatim while we were scoping a project to replace the spreadsheet her operations team had been running the business on for six years. She wasn't worried about the interface, or whether the new app would look nice. She was worried about something much more specific and much harder to see: formulas nobody fully remembers writing, built up one small fix at a time over years, each one encoding a rule someone needed on some particular Tuesday and never wrote down anywhere else.

That fear is completely reasonable, and I'd be more worried about a client who didn't have it. A spreadsheet that's run a business for years isn't just data. It's accumulated logic, and the whole risk of a migration is losing some of that logic quietly, in a way nobody notices until a number comes out wrong three months later. Here's the actual process I use to make sure that doesn't happen.

Step one: read the workbook like a document, not a database

Before any code gets written, I go through the workbook itself: every formula, every pivot table, every macro. Not skimming it to understand roughly what it does, actually reading each one to find where the real rules live.

This step usually turns up things the client themselves had forgotten about. A pricing formula with a conditional buried three levels deep that applies a different discount for a specific customer type under a specific condition. A macro that reformats a report in a very particular way because, it turns out, that's the exact format someone's accountant insisted on years ago. None of this is written down in a requirements document anywhere, because there is no requirements document. The spreadsheet is the documentation, whether anyone intended it to be or not.

One of my own products, a card reconciliation platform I still run today, started exactly this way: one large workbook, with formulas and pivot tables that had quietly grown into the real rulebook for how reconciliation worked. The only way to build the platform correctly was to go back through that workbook line by line, which is exactly the same step I now do for every client's spreadsheet before I touch a line of application code.

Step two: define a small first version, not everything at once

The instinct, once you've read through the whole workbook, is to try to migrate all of it at once. I push back on that every time. A small first version, covering the part of the workbook that matters most right now, gets built and proven correct far faster than an attempt to replicate the entire spreadsheet in one pass.

The rest doesn't get lost. It gets scoped for a later phase, and in the meantime it keeps living in the spreadsheet exactly as it always has. Nothing about this first version needs to be the whole picture. It needs to be the first provably correct slice of it.

Step three: migrate the data, then check the math against itself

Once the first version is built, the data gets imported, and then comes the step that actually answers the fear my client voiced at the start of this article: the app's totals get compared, side by side, against the spreadsheet's totals. Same inputs, same period, same categories. If a number in the app doesn't match the number the spreadsheet produces for the exact same data, that's not a rounding error to wave away. That's a formula the app hasn't correctly reproduced yet, and it gets tracked down and fixed before anyone relies on the app for anything real.

This isn't a one-time check. It runs across enough different scenarios, and often enough edge cases on purpose, like the one customer with the unusual discount, to be confident the match isn't a coincidence on a handful of easy rows.

Step four: run both in parallel until the app proves itself

Here's the part that should be the most reassuring, and usually is once clients see it in practice: nobody switches over on faith. The team keeps using the spreadsheet exactly as before, and the app runs alongside it, for however long it takes, until the app has consistently produced the same results as the spreadsheet across real, live data, not just the test cases from the migration itself.

Only once that parallel period proves the match, consistently, across enough real activity, does the switch actually happen. Nobody is asked to trust the new system on day one. They're asked to watch it agree with the old one, repeatedly, until trusting it stops being a leap and starts being an obvious conclusion from the evidence sitting in front of them.

Why this order matters more than the code itself

The code for a web app replacing a spreadsheet usually isn't the hard part. Reading the workbook carefully enough to find every rule actually living inside it, and then proving, number by number, that none of it got lost along the way, is the part that actually protects you.

Skip the reading step, and you migrate a guess at what the spreadsheet does instead of what it actually does. Skip the parallel-run step, and you find out about the gap after it's already cost you something.

What this buys you

Done this way, the day you finally retire the spreadsheet isn't a leap of faith. It's the last step of a process that already proved, with real numbers, that nothing was lost along the way. The years of logic buried in those formulas don't disappear into a rewrite. They get carried over, checked, and carried forward into something that's actually built to grow.

If your business is still quietly running on a spreadsheet you're both relying on and nervous about, that's exactly the conversation worth having before anything gets touched.

Let's talk through your situation.