Recently, I was having a conversation at work about how we should implement a feature. I was advocating for one particular approach, and one of the reasons I preferred it was that I thought it would be easier for AI agents to work with. The structure was more explicit, the possible states were easier to reason about, and it would give us better opportunities to automate verification and put guardrails around future changes.
One of the stakeholders pushed back with a very reasonable point: we shouldn't design software a certain way simply because it is easier for AI agents. We should design it based on what is best for our users.
I agree completely.
But the conversation made me realise that there is an important part of my reasoning that I hadn't articulated well. I wasn't putting the AI agent ahead of the user. I was still trying to find the solution that gave us the best combination of user experience, reliability, simplicity, time to market, implementation cost, operational cost, and long-term maintainability. The fact that an agent could understand and verify the resulting system more easily was one of the variables in that equation, not the objective itself.
That distinction matters because I think AI is changing the economics of software architecture in a way that we haven't fully absorbed yet.
The cost of writing software is changing
For decades, one of the biggest constraints in software development was the cost of producing software. Developers had to understand the problem, design the solution, write the code, review it, test it, debug it, and maintain it. Engineering capacity was scarce, so reducing the amount of implementation work required was extremely valuable.
AI coding agents are changing this equation. They can generate implementations, write tests, refactor code, explore unfamiliar codebases, migrate APIs, and perform many other tasks at a speed that would have been difficult to achieve with humans alone.
But there is an important asymmetry here: generating code is not the same thing as establishing that the code is correct.
An agent can produce a thousand lines of code in minutes. That doesn't mean we can establish in minutes that those thousand lines correctly implement the desired behaviour, don't introduce regressions, preserve important invariants, and interact correctly with the rest of the system.
This means that as the marginal cost of producing code decreases, another cost becomes relatively more important: the cost of verification.
And verification isn't something we pay for once.
We verify software when we initially build it. We verify it when we change it. We verify it when we refactor it. We verify it when dependencies change. We verify it when another feature interacts with it. We verify it when an AI agent modifies it. We verify it when a bug is fixed. We verify it when we migrate data. We verify it when we upgrade infrastructure.
Implementation costs are often largely one-off. Verification costs are recurrent.
That changes the architectural equation.
Implementation cost is not the whole cost
Imagine that we have two possible implementations for the same feature.
Solution A costs $100,000 to implement, but because the architecture doesn't provide strong guarantees, every subsequent change requires significant testing, review, and regression checking.
Solution B costs $120,000 to implement, but the architecture makes many invalid states impossible and gives us strong automated guarantees about the behaviour of the system.
If we only look at implementation cost, Solution A appears cheaper.
But software doesn't stop costing money when the initial implementation is complete.
If Solution A requires an additional $20,000 every year in verification and regression work while Solution B requires only $5,000, then the initial $20,000 saving disappears very quickly. Over the lifetime of the system, the more expensive implementation can become the cheaper system.
The exact numbers aren't important. The important thing is that verification is recurrent.
This is why I think we need to start treating verifiability as an architectural concern.
When comparing two architectures, we shouldn't only ask how much they cost to build. We should also ask how cheaply and reliably we can establish that they are correct over the lifetime of the system.
Verification isn't just testing
When I talk about verification, I don't mean that we should simply write more tests.
Tests are extremely useful, but there is a more powerful form of verification: designing the system so that certain classes of incorrect behaviour cannot happen in the first place.
There is a huge difference between saying, "We have tests that check this invalid state doesn't happen" and saying, "This invalid state cannot be represented by the system."
The latter is an architectural property.
Strong types are a simple example. If a function accepts a UserId rather than an arbitrary string, the type system can eliminate an entire class of mistakes before the program runs. Database constraints can prevent invalid relationships. State machines can restrict which transitions are possible. Schemas can prevent malformed data from entering a system. Idempotency can eliminate entire classes of duplicate-operation bugs. Explicit boundaries can reduce the number of possible interactions between components.
In each case, we are moving some of the burden of verification away from humans and tests and into the structure of the system itself.
The system becomes easier to verify because the system itself provides guarantees.
A database can become part of the state machine
Consider a workflow where a piece of data moves through several states.
Perhaps it starts as Created, then becomes Validated, then Processed, and finally Completed.
One way to implement this is with a single event table:
WorkflowEvents
id
workflow_id
event_type
payload
created_at
The application then needs to determine whether a particular event is valid given the previous state. The code needs to understand which transitions are allowed, whether the previous event exists, whether the payload is valid for the event type, and whether the workflow has reached an impossible state.
We can write tests for all of this. We can write application-level validation. We can ask an AI agent to reason about the state machine. We can review the implementation.
Another approach is to model the workflow more explicitly in the persistence layer. We could have event-specific structures where each stage references the previous stage through a foreign key, with schemas specific to that event.
Conceptually:
Created
↓
Validated
↓
Processed
↓
Completed
Validated cannot exist without a corresponding Created. Processed cannot exist without the appropriate Validated record. Completed cannot exist without the preceding state.
Each event can also have a schema that expresses the data required for that particular stage.
Now the database isn't just storing the state of the workflow. It is helping enforce the workflow.
We have effectively moved part of the finite-state machine into the persistence model.
I'm not suggesting that this is always the right design. It introduces its own complexity and trade-offs, and there are many workflows where a simpler event table or a different state-machine implementation would be preferable. The important point is not that one particular architecture is universally superior.
The important point is that the architectural choice changes the cost of verification.
With the first design, we may need to repeatedly establish through application logic and tests that invalid transitions cannot occur.
With the second design, some invalid transitions simply cannot be persisted.
That is a very different property.
Make invalid states unrepresentable
This is an old idea in software engineering, but AI makes it increasingly valuable.
If we can make an invalid state unrepresentable, we don't need to repeatedly verify that nobody has accidentally created that state.
Consider the difference between these two statements:
"We have tests proving that this state should never happen."
and:
"The architecture makes this state impossible."
The second statement is much more powerful.
It means that a future developer doesn't need to remember the rule. A future refactor doesn't need to rediscover the rule. An AI agent doesn't need to infer the rule from a collection of tests and documentation. A code reviewer doesn't need to notice a subtle violation.
The constraint is part of the system.
This is what I mean when I talk about verification becoming an architectural concern. Architecture can determine not only what the system is capable of doing, but also what incorrect things the system is capable of doing.
AI makes these properties more valuable
This is where AI agents enter the picture, but I don't think the argument should be "design software for AI."
The better argument is that AI increases the rate at which software can change.
If the number of changes increases, the cost of verifying those changes becomes more important.
Imagine two systems. In the first, every change requires a human to reconstruct a complicated mental model of the system and determine whether a subtle invariant has been preserved. In the second, the architecture expresses many of those invariants through types, schemas, constraints, contracts, and automated checks.
The second system is not merely easier for an AI agent to work with. It is easier for everyone to work with.
The agent benefits because it has stronger boundaries and clearer feedback. Developers benefit because there is less implicit behaviour to remember. Code reviewers benefit because more correctness properties are mechanically enforced. Operations benefit because fewer invalid states can reach production.
AI simply makes the difference more visible because we are increasing the volume and speed of change.
If AI can produce changes faster than humans can safely verify them, then architectures that reduce the cost of verification become increasingly valuable.
Verification is a recurring cost
This is probably the most important economic point.
Suppose Architecture A costs 10% less to implement but requires significantly more effort to verify every time it changes.
Architecture B costs 10% more to implement but gives us strong structural guarantees that dramatically reduce the cost of verification.
If we only look at the initial project, Architecture A may look attractive.
But software is not a project that ends when the feature ships. It is a system that continues changing for years.
The implementation cost happens once. The verification cost happens again and again.
Every feature built on top of the system pays some of that verification cost. Every refactor pays it. Every migration pays it. Every AI-generated change pays it.
This creates a compounding effect.
A small amount of additional complexity that buys a strong, reusable verification guarantee can potentially pay for itself many times over.
This is why I think architecture discussions need to consider the lifetime economics of verification, rather than treating testing and verification as something that happens after architecture has already been decided.
Verification as a first-class quality attribute
We already talk about architecture in terms of qualities such as performance, scalability, reliability, security, availability, and maintainability.
I think we should increasingly ask another question:
How verifiable is this system?
Not simply:
"How easy is it to write tests?"
But:
"How cheaply and reliably can we establish that this system is behaving correctly?"
Those are different questions.
A system can have excellent test coverage and still be difficult to verify. It might have complicated state transitions, implicit dependencies, weak contracts, highly coupled components, or many possible invalid states.
Conversely, a system can be designed so that its structure itself provides useful guarantees.
That could mean strong types. It could mean database constraints. It could mean explicit state machines. It could mean narrow interfaces, deterministic components, schemas, transactional boundaries, idempotent operations, or other forms of architectural constraint.
The common property is that correctness becomes cheaper to establish.
This changes architecture trade-offs
I think this also changes how we should evaluate competing solutions.
Historically, we might ask:
Which solution is cheaper to build?
Which one is simpler?
Which one performs better?
Which one is easier to maintain?
Those questions still matter.
But I think we should add:
Which solution is cheaper to verify?
Which solution makes more invalid states impossible?
Which solution gives us stronger automated guarantees?
Which solution makes regressions easier to detect?
Which solution reduces the amount of behaviour that humans have to repeatedly reason about?
Which solution gives automated agents better boundaries and feedback?
Which solution reduces the blast radius of an incorrect change?
The interesting thing is that these questions can change the answer.
A solution that costs more to implement can be the economically better solution if it substantially reduces the recurring cost of verification.
And this doesn't mean the most constrained architecture always wins. Constraints have costs too. Excessive constraints can make a system unnecessarily rigid, difficult to evolve, or more complicated than the problem warrants.
The point is not to maximise constraints.
The point is to recognise that constraints have economic value when they reduce the cost of establishing correctness.
The question I now want to ask during architecture discussions
Coming back to that conversation at work, I still agree with the stakeholder's principle: the user should come first.
But I now think there is a missing dimension in how we reason about what is best for the user.
The question isn't:
"Which architecture is easiest for the AI?"
Nor is it simply:
"Which architecture is cheapest to implement?"
The question is closer to:
"Which architecture gives us the best overall outcome for the user, given the lifetime cost of building, operating, changing, and verifying the system?"
Sometimes the answer will be the simplest possible implementation.
Sometimes it will be the architecture that is easiest for an AI agent to modify.
Sometimes it will be an architecture with significantly more upfront complexity because that complexity gives us guarantees that would otherwise have to be repeatedly verified.
And sometimes the right answer will be something completely different.
The important thing is that verifiability is now part of the trade-off.
The architecture should help us prove that it is correct
AI-assisted development is often discussed in terms of how quickly we can produce software.
I think that is only half of the story.
If AI makes implementation dramatically cheaper, then our scarce resource increasingly becomes the ability to establish that what we produced is correct.
That means the architecture of a system is no longer just about making the desired behaviour possible. It is also about making incorrect behaviour difficult to express, easy to detect, and cheap to rule out.
The most interesting architectural decisions may therefore be the ones that turn verification from a recurring human activity into a property of the system itself.
Because the ultimate goal isn't to build software that AI can generate quickly.
It's to build software that we can continuously establish is correct.
And if we can design the architecture so that the system helps us do that, then verification stops being something we bolt onto the end of development.
It becomes part of the architecture.
Top comments (2)
Data pipelines have the worst version of this. I had a fuzzy matching rule that took maybe 3 hours to write and then spent the next two weeks figuring out why recall on Korean company names had quietly dropped 8 points. The pipeline wasn't traceable enough to replay the pre-change state, so debugging meant basically re-running history on a subset and eyeballing diffs. The architectural cost I'd deferred was the traceability itself, and I've been paying installments on it ever since.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.