You Did Discovery. You Just Did It Backwards.
by Jonathan Simmons, Founder
Open Your Deployment Settings and Look
Part of the system lives on one platform. Another part talks directly to a second one, because at the time that was the fastest path to a working thing, and it was.
There are two ways a user can end up authenticated, and both are live. One came from the first version, one from the week you added the integration. Neither is wrong exactly. They just don't know about each other.
There's a service you picked in week two. It was the obviously correct pick in week two. It no longer quite fits what the product became, so you route around it instead of removing it, because removing it means touching four other things and you're not sure which four.
Here's what I want to be clear about: none of that was careless. Every one of those choices was locally correct when it was made. You had a problem in front of you, you picked a reasonable way to solve it, it worked, you moved on. That is exactly what you were supposed to do.
The thing you built works. People use it. That is not a small achievement and I'm not going to spend this post walking it back.
You Did Not Skip Discovery
The line you'll hear, if you show this to someone who does software for a living, is that you skipped discovery.
That's wrong, and it's a little condescending, and it's worth taking apart because the wrong diagnosis leads to the wrong fix.
You didn't skip discovery. You did an enormous amount of it. You learned who actually uses this and what they actually do with it. You learned which feature you were certain about turned out to be decoration, and which throwaway thing turned out to be the reason anyone shows up. You learned the real shape of the problem, which is almost never the shape you assumed at the start.
That is discovery. That is the whole activity. You did it thoroughly.
You just did it after committing, one decision at a time, instead of before.
Which means: every architectural decision got made at the moment you understood the problem least.
Why the Order Is the Entire Problem
Discovery isn't a ritual. It has one job, and the job is sequencing. It front-loads the learning so that the decisions get made with more information rather than less.
Build-first inverts that. Not partially. Completely.
You chose your data model in week one, which is precisely when you understood the domain least. You picked your deployment topology before you had any idea what the load pattern would be. You decided where state lives before you knew which state mattered. Every one of those got made at the point of minimum information.
And this is the part that turns an annoyance into a structural problem: each decision constrains the next one.
The data model you picked in week one narrowed the reasonable options for how you'd handle permissions in week four. The auth approach you settled on in week four made one integration easy and another one awkward, so in week nine you picked the easy one. Not because it was better. Because it was the one your earlier self had left the door open for.
So it isn't one uninformed choice. It's a chain, where the earliest and least informed link sets the direction for everything downstream of it. By the time you understand the problem properly, the shape of the system was determined months ago by a version of you who didn't.
Nobody Is Carrying the Why
There's a second thing happening underneath this, and it's structural rather than anyone's fault.
The agent that built a chunk of this six weeks ago has no memory of building it. Same provider, same model, doesn't matter. There is no thread connecting the reasoning then to the code now. It's not a flaw in the tool. It's just what these things are.
The consequences of that decision are permanent. The rationale is gone.
So when you come back to a piece of the system and ask "why is it like this," there's often no answer available anywhere. Not in your head, because you were reviewing output rather than making the call. Not in the code, because the code records what was done and not why. Not in the tool, because the tool doesn't remember.
You end up unable to distinguish deliberate from incidental. That distinction is the thing you need most when you're deciding what's safe to change, and it's the one thing that didn't get written down.
"But That's Just Iterating"
Here is the strongest objection, and if you're sharp you've been holding it since the second section.
Learning as you go is good product work. Ship, learn, adjust. That's lean. That's every decent methodology of the last twenty years. You're describing normal iteration and calling it a pathology.
That's right. And I mean it: the objection is correct, and if I can't answer it the rest of this doesn't stand up.
So here's the answer.
Iteration always worked because prototypes got thrown away.
That was the load-bearing part, and nobody talked about it because it happened automatically. You built a prototype to learn something. It was rough. It was held together with hardcoded values and one file doing six jobs. It taught you what you needed to know, and then it went in the bin, because it was never going to survive contact with a real user. You rebuilt the thing properly, knowing more.
The demolition was built into the process. Not as a discipline you had to maintain, but as a consequence of prototypes being genuinely too shabby to keep.
What's changed is that the shabby version now works well enough to keep.
That's it. That's the entire shift. The output of your learning process is no longer disposable, so it doesn't get disposed of. It ships. It gets a customer. It becomes the thing the next piece is built on top of.
Every throwaway becomes load-bearing.
The enemy was never iteration. Iteration is fine, iteration is how anyone finds out anything real. The enemy is iterating without ever demolishing, which is a genuinely new situation, because the demolition step used to be free and involuntary and now it's neither.
What This Actually Costs You
I'm not going to call it technical debt. That phrase has been worn down to mean "code somebody doesn't like," and it points you at the wrong repair.
The real cost is this: the shape of your system encodes a version of the problem you no longer believe in.
You have a much better theory of what you're building now than you did in month one. The architecture still reflects the month one theory, because that's when it got set. The two are out of sync, and the system keeps pulling you back toward the old one, because that's the direction all the paths run.
And the second cost, which is worse: you can't tell which parts are conviction and which parts are leftovers.
Some of what's in there represents a real decision you'd defend today. Some of it is residue from an experiment that happened to work on a Tuesday. From the inside they look identical. Both are just code that runs. So you treat all of it as load-bearing, which means you stop touching any of it, which is how a product quietly stops moving.
Doing the Demolition Late
You can run the missing step retroactively. It costs an afternoon and you can do it alone, no tooling required.
Start by listing the decisions that are hardest to reverse. Not all of them, just the expensive ones:
- The data model. How the core entities relate, what's a first-class thing and what's an attribute of something else.
- Auth and identity. How someone becomes a known user and what that grants them.
- Where state lives. Which system is the source of truth for each important thing.
- Deployment topology. What runs where, and what has to be up for what else to work.
Four is usually enough. These shape everything above them, and nobody revisits them because revisiting them feels enormous.
Then, for each, ask exactly one question: knowing what I know now, would I choose this today?
Not "is it working." It's working, that's why it's still there. The question is whether you'd pick it fresh.
The answers sort into two piles, and the sorting is the entire point:
- Still right. You'd choose it again. Now you know it's a real decision. Write down why in one sentence and it stops being a mystery to your future self.
- Still here. You wouldn't choose it again. It's not a decision. It's a survivor.
You don't have to fix anything in the second pile today. Most of it you won't fix for months, some of it never. But once it's named it stops being invisible, and it stops silently constraining the next decision. You'll know when you're building on a survivor rather than a conviction, and you'll price the choice accordingly.
That's the demolition step. It doesn't require knocking anything down. It requires knowing which walls you'd build again.
The bottom line: you learned as you went, which is fine and normal and how most good products actually get made. What's new is that nothing you built along the way ever got thrown away, so your architecture isn't a record of what you decided. It's a record of what you used to believe.