Designing to Maturity Before Building Anything
Before I built anything, I spent weeks doing nothing but talking. The question that made it useful was not what to build. It was which decisions would be expensive to change later.
Before I built anything, I spent weeks doing nothing but talking.
Not planning in the project sense, and not writing specifications. I was emptying thirty years of operating knowledge into a conversation and asking a single question over and over: given what I just told you, what does that imply about how this has to be built?
That is the part of using AI that almost nobody talks about, because it is not impressive to watch. There is no code, no demo, and nothing to show anyone. It is a person describing how freight actually moves and how buyers actually choose, and then asking what that means structurally. I would explain how a shipper handles an exception, and the useful reply was not a feature. It was a question about whether that exception needed to be recoverable later, which is a question about whether it gets recorded, which is a question about the shape of the database. Domain knowledge in, structural implications out.
I did not know enough to ask the right architectural questions. I did know enough to describe the problem exactly, and it turns out that is the input that matters.
But there is a failure mode sitting right next to this, and I walked into it early.
If you ask what the best architecture would be, you will get an answer, and the answer will be a cathedral. Every abstraction, every layer, every generalization for a case you may never have. It is not wrong exactly, it is just a design for a company that does not exist yet, and building it would have taken a year and produced nothing anyone could use.
The question that actually works is different, and it took me a while to find it.
Not "what is the best way to build this." Instead: which of these decisions will be expensive to change later?
I asked that question, in one form or another, several hundred times. Is this the most robust option available. Is this enterprise grade. Is there a version of this that holds up better under load, or under scrutiny, or in two years. It became a reflex, and I eventually wrote it into the project's standing instructions so that it would not depend on me remembering to say it.
I still said it constantly.
The reason is worth understanding, because it is the single most important thing I have learned about building this way. Memory is not what AI is good at. It is extremely good at producing a correct solution to the problem in front of it, and it is not reliably good at producing the same correct solution it produced last week to the same class of problem. There are many routes to a working answer, and left alone it will take a different one each time, because each route is genuinely fine on its own.
That is how you end up with forty good solutions stapled together instead of one application.
So the consistency has to come from the builder. I hold the pattern, I notice when a proposal solves something differently than we solved it the last time, and I send it back. Not because the new way is wrong, but because two ways of doing the same thing is a maintenance problem that compounds and a comprehension problem for whoever reads it next, which on this project is me in six months.
I am not going to pretend I caught all of it. There are almost certainly places in this codebase where the same problem is solved two ways, and I will find them eventually. Consistency is the goal rather than the claim. What makes it achievable at all is the record, because every meaningful decision gets written down with the reasoning attached, and the reasoning is the part that matters. The decision will get re-proposed. The version of me reviewing it in four months will not remember why we ruled the alternative out.
Now, the sorting itself.
Some decisions are cheap to reverse. How a screen is laid out. How a question is worded. What a dimension is weighted. Those get decided fast, with whatever information is available, and changed later when better information shows up. Being wrong about them costs an afternoon.
Other decisions are effectively permanent, not because the code is hard to change but because the consequences accumulate in the data. Those are the ones I designed at maturity from the first day, before there was a product to justify them.
Whether a vendor has a stable identity. Every vendor in the catalog got a permanent identifier at the moment it entered, along with the resolution work to make sure the same company entering twice does not become two companies. Skip that, and a year later the same vendor exists three times under slightly different names, with match history split across all three and no reliable way to reassemble it. That is not a refactor. That is an archaeology project, and it never fully succeeds.
Whether facts are recorded or merely current. Every answer, every score, every state change is written to an append-only record rather than updating a field in place. On day one that looks like pure overhead, because there is no history worth reading yet. The point is that you cannot go back and record something you did not record. History is the one thing a system can never retrofit, and the moment a buyer asks why a vendor ranked third eight months ago, either the record exists or it does not.
Whether a category is data or code. This one came out of the domain rather than out of engineering. Supply chain buying is fractured and always has been. A shipper does not buy one system, they buy a transportation system and a dock system and a maintenance system and a vetting system, from different vendors, on different cycles, with different people deciding. Any platform serving that market that only works for one category is solving a fraction of the problem by construction. So the first vertical was built as a pack from the beginning. Writing it directly into the engine would have shipped faster and would have become a rewrite the moment the second category arrived. Instead a vertical is data that a generic evaluator runs, which was more work for zero visible benefit while exactly one vertical existed, and which has paid for itself every time since.
Whether tenants are isolated. The platform was built so that one organization's data is structurally separated from another's, long before there was a second organization. Retrofitting isolation into a system that assumed a single tenant is one of the more reliable ways to spend six months and introduce a security incident on the way through.
Whether somebody else can run this under their own name. White-label was designed in from the beginning rather than imagined as a later product. A consultant running a selection for their client can operate on this platform under their own brand, with their own configuration layered onto the scoring, while the engine underneath stays exactly the engine. They can weight what their practice believes matters. They cannot change how fit is computed, they cannot change what gets disqualified, and they cannot reach the record. The configuration is theirs and the mechanism is not, which is the only arrangement under which a white-label version means anything, because a white-label of a system the operator can alter is a logo on somebody else's opinion.
Whether the platform knows who it is talking to. Personas were built in at the same time, for the same reason. A dock scheduling system serving a shipper is not serving a 3PL, and an electronic logging device serving an owner-operator is not serving a private fleet with its own maintenance shops. Every question, every gate, and every score is persona-aware from the first pack forward. Adding that later would have meant going back to every buyer who had already answered and asking them to start over, which is the kind of thing you only do once before people stop taking your calls.
How security is enforced. Security added afterward is a different product than security designed in, and the difference is not the feature list. It is whether the system contains any place where the rule can be quietly skipped.
The clearest example is data release. When a vendor receives a buyer's requirements they see a scoped slice rather than the whole assessment, and that scoping runs through exactly one function. Not a permission check on every route, which is the common pattern and the reason leaks happen, because eventually one route forgets. One gate means one place to audit, one place to reason about, and one place to be wrong, and that last one is the point. A system with a dozen permission checks has a dozen chances to hold an inconsistent one.
The audit record is immutable, with a single deliberate exception, and the exception is worth describing because it is where two obligations collide. Privacy regulation gives a person the right to have their personal data erased. An audit obligation says the record cannot be altered. Most systems resolve that by quietly making the audit log editable, which means it was never an audit log. Instead there is one narrow carve-out: on an erasure request the actor identity is set to null and nothing else changes. The event still happened, the timestamp still stands, the decision is still recorded, and the person is simply no longer named in it.
There is also a rule that no third-party service gets integrated until its data processing agreement is recorded. Not reviewed afterward, not tracked on a list somebody maintains. The agreement being on file is a precondition for the integration existing at all, which is the only version of that rule that survives a deadline.
And every aggregate carries a suppression floor. Any statistic drawn across the vendor base is withheld below a minimum count, because a number computed from two vendors is a number about two vendors, and anyone who knows the category can name them. That is a security control wearing an analytics label, and it exists because the alternative is publishing a de-anonymization tool and calling it a benchmark.
The rest is ordinary and unglamorous. Rate limiting on the routes that need it, audit logging on every state-changing operation, credential rotation treated as an all-dependent-systems exercise rather than a single edit, and framework upgrades to clear vulnerabilities treated as their own work rather than something folded into a convenient future.
Whether the platform can answer questions about itself. Analytics is a data-shape decision wearing a reporting costume. If facts are not captured at the right grain, with the right timestamps and the right lineage, no amount of dashboard work later recovers what was never written down.
Three decisions carried the weight.
Every fact is stored with two separate time axes: when the thing was true in the world, and when we learned it. That sounds academic until somebody asks why a vendor ranked third in March. Answering it requires knowing what was true in March rather than what is true now, and those are different questions that most systems cannot tell apart because they only ever kept one clock. A single-clock system can tell you what it currently believes. It cannot tell you what it believed at the time, and what it believed at the time is the only thing that explains a past decision.
Every derived number carries a fingerprint of the inputs that produced it. If a vendor's capability answer changes after a follow-up interview, the system can identify every score, every match, and every aggregate computed downstream of that answer and flag them as built on a superseded input. Without that, a correction upstream leaves stale numbers scattered across the system with no way to find them except by remembering where they were.
And entity resolution is propose-then-confirm rather than automatic. When the system believes two records describe the same company, it proposes the merge and a person confirms it, and only the confirmation becomes canon. Automatic merging is faster and it is wrong, because its failure mode is silent: two different companies collapse into one, their histories combine, and nothing in the data indicates that anything happened.
There is one more rule in this area that sounds like housekeeping and is not. No data shape may exist in the demonstration environment that production could not produce. A demo showing something the real system cannot generate is a lie with a good interface, and the temptation to build one is constant.
The same discipline governs what gets published. Estimates do not surface unless they clear a confidence threshold, which means the platform will often say nothing rather than say something weak. Silence is a worse demo and a better product.
That is eight decisions. There were not many more, which is the point I want to land on.
Designing to maturity does not mean building the mature product. It means identifying the small number of decisions that foreclose the future, getting those right at full scale, and building the smallest correct version of everything else. Most of the platform on day one was thin. Screens were plain, flows were incomplete, and there were categories that existed only as an empty table. What was not thin was the identity model, the record, the evaluator boundary, the isolation, the white-label seam, the persona model, the security posture, and the analytics grain, because those were the things that could not be added later.
The AI did not make those calls. What it did was let me convert operating knowledge into structural questions fast enough to see the shape of the thing before I committed to it. A year of building would have taught me the same lessons. The conversation taught me in weeks, and the difference is that I still had all my options.
If you are considering building something in a domain you already know well, this is the part I would spend your time on, and it is available to you right now.
You do not need to know how to architect a system. You need to be able to describe your problem precisely, which you can already do better than almost anyone, and then keep asking what that description implies about the structure. The answers come back. Your work is the sorting, and the sorting question never changes: if I get this wrong, what does it cost me to fix?
Most things are cheap. Get those wrong quickly and keep moving, because the information you need to get them right does not exist yet anyway. A small number are not cheap, and in my experience they are almost always about identity, about history, about boundaries, and about who is allowed to see what. Spend the extra week there. Nobody will notice you did it, there will be nothing to show anyone at the end of it, and it is the only part of the build you cannot come back and do later.
The weeks I spent talking before writing anything felt like procrastination while I was doing them. They turned out to be the most productive weeks of the entire build.
Selecting supply chain technology?
PreShiftIQ matches buyers to vendors on measured fit across TMS, dock scheduling, ELD, carrier vetting, and fleet management. Vendors pay for outcomes, never for influence, and the buyer match is free.
See how matching works at preshiftiq.com/how-it-works.
Next in the series: building to enterprise grade from the first commit.

