Introduction
Lately, some of the words I have repeated in meetings and code reviews sound different to me than they used to.
Choose technology that is easy to hire for. Build on a mature ecosystem. Avoid large rewrites whenever possible. Trust well-known external implementations. Consider the cost of tests, and write them only where they matter most.
All of this was good engineering wisdom. It was a set of tools that finally began to fit our hands after years of failure. I am not saying that all of it was wrong.
But AI has already changed the assumptions that supported that wisdom.
The time it takes to write code. The time it takes to learn unfamiliar technology. The time it takes to make a large change. The time it takes to write and maintain tests. The time it takes to read and inherit someone else's code.
Engineering thinking does not exist independently of these costs. What took time and what was difficult shaped what we avoided, what we trusted, and what we valued.
Philosophy can sound harder than this, as if it lives outside time. But most engineering philosophy was born from the constraints of ordinary work.
Now that the shape of those costs has changed, we should put our familiar tools back on the table and ask whether we still need them in the same way.
The Criteria For Technology Choices Have Changed
Team familiarity used to be one of the strongest criteria in technology selection.
Can the people already here write it? Are there enough learning resources? Can we search for an answer when something goes wrong? Can we hire engineers with experience in it?
These questions still matter. But their baseline as selection criteria has clearly fallen.
With AI, an engineer can read a project in an unfamiliar language, learn its typical structure, and build small working pieces while learning, all in one continuous motion. The surface area of code one engineer can touch has grown.
Ecosystem familiarity is no longer an absolute prerequisite for choosing technology. We should treat it as something that can be acquired after the choice.
The same is true of the hiring market. The number of people already experienced with a technology still matters, but it should no longer decide the choice by itself.
Instead, we should care more about whether the lead engineer or chief engineer who will carry long-term responsibility for the system finds the technology interesting to work with.
Interest is not merely a matter of mood. The desire to keep digging when a difficult problem appears, and the desire to keep improving a system over years, directly affect the quality of maintenance.
Technology maintained for a long time is a tool touched a little every day. Its feel should matter as much as performance and hiring availability.
Now that AI has expanded what people can write, humans have more freedom to choose what they want to keep writing.
Not only whether the technology is famous or easy to hire for, but whether the person responsible can continue to like the tool. And whether that preference is supported by sound design.
Technology selection should become human again.
Large-Scale Migrations Are Now Realistic
One reason technical debt was frightening was the size of the change required to repay it.
Remove an old framework. Migrate hundreds of screens. Replace deprecated APIs. Change the language or runtime.
Migrations like these required a great deal of time and many people. That is why technology selection placed so much weight on choosing something that could be used for as long as possible.
Once something had been built, it could not easily be moved. We planned the future around that assumption.
But today, even very large software projects are changing their implementation languages.
Bun completed its full migration from Zig to Rust. Flow migrated from OCaml to Rust. The Rust port of React Compiler has already been merged into main.
These are not experiments that might become real someday. They are completed large-scale migrations integrated into existing projects.
Of course, none of them was handed to AI and rewritten overnight. They required long-term design, verification, performance evaluation, and human judgment.
Even so, AI is enormously useful for reading an existing implementation, producing corresponding code, examining differences, and resolving test mismatches one by one. It is already common for migration changes like these to be built in collaboration with AI agents.
Now that the barrier to large-scale migration has fallen, our relationship with technical debt must change as well.
Debt does not disappear. Data migration, semantic differences, live operational state, organizational understanding, and contracts with users cannot be moved by generating code alone.
But the assumption that a choice cannot be changed for ten years is already breaking down. Destinations that once looked impossibly far away have moved within practical reach.
Technology choices should now be evaluated not only by how long they can survive, but also by how easily we can leave them when necessary. Clear boundaries. Behavior preserved in tests. Open data formats. The ability to replace one part at a time.
Good technology is not only technology we never need to abandon. It is also technology we can let go of cleanly.
Specifications Must Also Be Executable
Natural-language specifications are necessary.
Why are we building this? Whose problem are we solving? What must never happen? When values conflict, which one takes priority?
Intent like this must remain in human language.
But natural language alone is a poor place to store the answer to a question like, "How should this system behave for this input?"
Different people imagine different boundary conditions from the same sentence. The implementation changes while the prose remains old. AI does not interpret ambiguous language in exactly the same way every time either.
Prose runs once, inside the reader's head. A test can run the same question again and again.
Specifications must therefore also exist in executable form.
Tests, types, schemas, contracts, state machines, properties, lint rules. The right form depends on the subject, but the important property is that a machine can read it, execute it, and detect divergence.
TypeScript has long been criticized for lacking a complete language specification, leaving the implementation and its tests as the de facto specification. That criticism has reasons behind it, and documentation for human understanding has not become unnecessary.
At the same time, in a world where AI generates large amounts of implementation and ports one implementation into another, a set of executable behaviors matters more than ever. Well-written prose is not enough. Tests that run on every change and expose differences give the implementation a place to return to.
Test262 is one of the best examples. ECMAScript has an exact natural-language specification, but it also needs an enormous conformance suite to verify that multiple implementations produce the same observable behavior.
Specifications and tests are not alternatives. We need both language that communicates intent to humans and representations that machines can verify repeatedly.
Tests Matter More, Not Less
Test code has always carried its own maintenance cost.
Change the implementation, and the tests must change too. Brittle tests slow development down. Try to test everything, and the tests themselves become a large system.
All of this is still true.
But AI has made it much easier to write tests, migrate existing tests, consolidate duplication, and infer intent from failures before fixing them.
At the same time, AI is increasing the amount of code being produced. If generation grows while verification does not, uncertainty simply accumulates inside the system.
AI lowers the cost of implementation, but it does not remove the need for verification. It increases it.
Every behavior that can be tested should be written as a test. Not only the happy path, but boundaries, failures, races, strange compatibility inherited from an old implementation, and incidents that happened only once. Everything a machine can check again should be made checkable.
Whoever turns everything testable into tests wins.
Tests are not only a quality-assurance mechanism. They are a way to place what the team has learned outside human memory. They are externalized memory.
They remain when people leave. They remain when chat history disappears. They can demand the same behavior even when the AI model changes.
Now that the maintenance cost of tests has fallen, we should test all the areas we once hesitated to touch.
OSS Sustainability Should Be Designed For Handoffs
Large OSS projects have long discussed the maintainer as a single point of failure.
Only one person understands the design intent. Only a few people can make a release. Issue priority and compatibility boundaries depend on one person's experience.
If that person becomes exhausted or their life changes, the project becomes difficult to continue.
AI does not solve this automatically. OSS maintenance is not only writing code. It also means making value judgments, rejecting changes, explaining decisions, and absorbing friction between people.
But OSS maintainers are AI users too. Issue classification, investigation, reproductions, test additions, compatibility checks, release notes, and migration support can all become cheaper.
More importantly, a maintainer can move more of their thinking and daily behavior into the repository.
Write down design principles. Show examples of changes that should be accepted and rejected. Turn compatibility into tests. Automate releases. Preserve the history of decisions. Make the same verification environment reproducible by anyone.
When these things exist, the barrier for someone else to fork the project and continue maintaining it falls dramatically. A fork becomes more than a copy of the code. It becomes an inheritance of how the project thinks and how it is cared for.
We should not define sustainability as the original author continuing forever. It should mean that other people can inherit the reasoning and verification after the author leaves. It should mean that the project can branch and continue as another community when necessary.
OSS sustainability should be designed around transferability, not around one maintainer staying forever. AI makes that transfer practical.
Vize Is Already Doing This
This is not only speculation about the future of OSS. I am already practicing this model in Vize.
Vize contains roughly 500,000 lines of source code. I maintain it alone, and recently I have automated most of that maintenance through AI.
Of course, I do not let AI write whatever it wants.
The ubugeeei Redundancy Guide records what Vize exists to do, what it prioritizes, and how issues should be discovered, reported, fixed, reviewed, and released.
It is not merely a contribution guide. It externalizes my values, decision criteria, review standards, and development rhythm so that Vize can continue moving even when I am gone.
I tell AI to read this document and follow it. The AI then reproduces my workflow with considerable accuracy: find a problem, create a minimal reproduction, file an issue, write a regression test, fix it, pass CI, and move on to the next problem.
I am not delegating judgment to AI. I move the criteria for judgment into the repository, then delegate the labor performed under those criteria to AI.
Vize is approaching 10,000 test cases. Every problem leaves a regression test. Every edge case that can be named is written down. Real projects are used for end-to-end verification.
If AI has lowered the maintenance cost of tests, the correct response is not to write fewer tests. It is to write as many as possible.
One person owns 500,000 lines, pins behavior with nearly 10,000 tests, documents their way of working, and makes AI reproduce it. This is not a strange heroic story. It is one form of OSS maintenance in the age of AI.
The goal is not to make humans unnecessary. The goal is to make "only I know how this works" unnecessary.
Sustainability in Vize means refusing to make myself the project's only runtime.
Hiring Should Optimize For Density, Not Headcount
The age of scaling by hiring more 80-point engineers is over.
The old model was to hire more engineers who could reliably produce 80-point performance, then scale development through headcount.
But headcount also scales the cost of communication, alignment, review, and distributed responsibility. Doubling the number of people does not double development speed.
Now that AI has expanded the scope one person can handle, one 100-point engineer with deep ownership is often stronger. At the same time, an engineer who previously produced 50-point performance can reach the old 80-point level with AI and a strong verification environment.
These scores do not represent the value of a human being. They are an intentionally crude metaphor for performance on a particular kind of work at a particular moment.
The point is not to return to the old slogan of an elite few, or to declare inexperienced engineers unnecessary.
The point is that AI has changed how individual capability appears, and hiring should no longer be treated as simple addition of headcount.
The ability to form a good question. The ability to doubt the answer. The ability to imagine how locally correct code could damage the whole system. The ability to turn a failure into a test and hand it to the next implementer.
Judgment, ownership, learning speed, and verification now matter more than typing speed.
The Relationship Between Trust And In-House Cost Has Changed
For a long time, we have used external code on the basis of qualified trust.
Microsoft made it, so it is probably fine. It is famous OSS, so it probably will not disappear suddenly. It has many users, so someone else will probably find the problem first.
This was not laziness. It was a rational cost calculation.
We cannot write, understand, audit, and maintain everything ourselves. We accepted incomplete trust in order to reduce the cost of building and maintaining everything in-house.
Of course, famous implementations still fail. Corporate strategies change. Projects end. Licenses change. Maintainers leave.
We trusted external code anyway because, in most cases, the cost of building it ourselves was higher.
AI fundamentally changes that relationship.
We can replace a small dependency ourselves. We can implement only a thin but critical boundary in-house. We can read an external implementation, transfer the behavior we need into our own tests, and leave when an incident happens.
This does not mean everything should be built in-house. In cryptography, authentication, databases, and distributed systems, the accumulated knowledge of past failures matters more than the amount of code. The fact that AI can produce a thousand lines does not mean it understands ten years of failure.
The question is no longer simply build or buy.
How far do we trust, and where do we begin to own? Can we read it when something goes wrong? Can we fix it? Can we discard it? Can we fork it? Can we constrain the behavior we need with our own tests?
We should not stop trusting external code. We should trust it in a form that preserves our ability to leave. Instead of placing everything in the size of a name, we should keep a road back to ourselves.
AI has made that option practical.
Rethink It All
AI does not remove every difficulty from software development.
Code still breaks. Specifications remain ambiguous. People become tired, organizations forget, and dependencies fail. There is also a real danger that generated code accumulates faster than anyone understands it.
Even so, several costs have clearly fallen.
The cost of entering unfamiliar technology. The cost of carrying out a migration. The cost of writing and maintaining tests. The cost of reading someone else's code and inheriting its maintenance. The cost of implementing a small but important part in-house.
When costs change, we should not keep making the same choices for the same old reasons.
Choose technology that the responsible engineer finds interesting, not only technology that matches the hiring market. Consider how easily we can leave, not only how long we can stay. Keep executable specifications beside natural-language specifications. Turn everything testable into tests. Design OSS continuity around transferability, not one person's devotion. Optimize hiring for the density of judgment and ownership, not headcount. Trust external names in a form that preserves the ability to leave.
This is not a rejection of old engineering. Yesterday's ideas were wisdom for surviving yesterday's constraints.
But the ground can change while we keep walking with the same map.
AI has rewritten more than code. It has already changed what we consider difficult, what we give up on, and what we trust.
So we should stop for a moment and pick up the words we have used for years.
Which of the things we valued still deserve to be valued? Which choices have become available now that their assumptions have changed?
Even before we have every new answer, we must test yesterday's correctness against today's cost structure.
Holding that question, and continuing to choose again, is the engineering philosophy of the age of AI.