It's been a while
Time flies. And here we are in April of 2025 and it looks like the weather right now is trade war with intermittent market crashes. Be that as it may I have written something pretty long. Or very long actually but I don’t want to post that here because trying to the formatting to a reasonable level would murder my will to live. So I wanted to share one of the chapters which is related to things that have been discussed here previously (systemic debt) and contains some of the work from there. What can I say, I’m lazy. But it does also go into how to start transforming an organisation to a new type of workflow on a pretty granular level. I thought it might be useful.
Adoption Strategies
We’ve painted a picture of an AI-augmented future for software development, one built on structured co-operation, rigorous specification, and automated workflows. We’ve explored the potential benefits – faster delivery, enhanced consistency, improved quality, and freeing up developers for higher-value tasks. We’ve also considered the impact on DevEx, Operations, and Infrastructure.
But knowing what the destination looks like and how to actually get there are two different things. Implementing such fundamental changes requires more than just buying some AI tools; it demands a conscious strategy for transforming teams, processes, and culture. This chapter focuses on the practicalities of adoption, the inevitable speed bumps and potholes.
How Do We Get There?
The journey towards specification-driven, AI-augmented development isn’t an overnight flip of a switch. It’s an evolutionary process that requires deliberate steps and addressing existing challenges head-on. I know, it sounds like management consultant speech for “We will bill you all the money” but trust me, I have enough to deal with, you have to walk this particular path yourself. The primary thing I would like you to keep in mind is that there’s a big difference between where people are mentally. Some might have played a bit with LLMs two years ago and left it at that. Others sit up late at night and fiddle with ollama just for the hell of it. A successful transformation requires that the distance between the outliers shrink and that the majority of people who are influential in the internal community are onboard. Push too hard before that has happened and you will face a backlash and have to back off and lose time. And in the words of Napoleon
Space we can recover, time never.
And with that, let’s talk about the things you need to consider.
Sooner or later it adds up to real money
There’s no getting around it, unless you have just started a new company—in which case, congratulations. We are all struggling with making payments on what we tend to refer to as technical debt. Since it has been such a big part of what I do for the last years specifically, I thought it would be good to at least in this context provide a nuanced explanation since it can otherwise easily become a nebulous boogeyman. Technical debt is generally portrayed as code shortcuts taken to deliver quickly, but this is a lot like blaming the paint job for a building’s structural issues after it burned down, exploded and collapsed over a pile of kittens. In that, rather confusing, order.
In reality, the problem is bigger, deeper, and quite a bit more philosophical than that. We really need to talk about system debt—a broader concept encompassing the incremental cost of many types of trade offs that can easily pile up, making systems clunky and difficult to maintain. Think of it as technical debt’s more complicated sibling, who not only skipped a few steps in coding but also neglected the architecture, forgot to update the documentation, and might have been sleeping through the company re-org. So right now, we’re going to walk through six kinds of system debt that go beyond the usual suspects: ontological debt, design debt, implementation debt, organisational debt, knowledge debt, and cultural debt. There won’t be a test but you might just find it useful as a tool for reasoning about the possible ways of solving problems by involving a completely different set of stakeholders.
Vocab 101
I might as well rip the band-aid and start with the most abstract one—ontological debt. A simple explanation is that it is what happens when the system’s vocabulary or core concepts don’t quite match up with what the system is actually doing. Or more specifically what it should be doing now. Think of it as having an app where every button is labeled “Submit,” even though one submits your payment and another submits your hopes and dreams into the void. Ontological debt sneaks in when the original terminology used in a system becomes irrelevant due to an incremental shift in the system’s purpose, more often than driven by evolving business needs.
Imagine you’re working on an e-commerce platform that originally only sold books, but now it’s selling everything from kitchen sinks to NFTs. The original data models might still refer to “Book ID” or “Author Name” even when the item in question is a pair of vintage sneakers that cost more than your first car. This mismatch between terminology and actual system use creates confusion and forces developers to perform mental gymnastics just to keep things straight. It’s as if the system is speaking an outdated dialect, forcing everyone to carry around a language dictionary just to understand what’s going on. Or more frequently, try to shoehorn everything into the original model because "it makes sense and it works and if it ain't broken…". Or a variant which is not uncommon as well—“We’re making so much money with this, how can there be anything wrong with it?”
The remedy is to acknowledge that these changes need to be made regularly and accept that business evolution isn’t something the system can simply ignore. Regular updates to domain models and system vocabulary can help bridge the gap between reality and your data structure’s stubborn nostalgia for the “good old days.”
Whiteboard regrets
Design debt is what happens when trade-offs made during the system’s initial architecture design come back to haunt you. When you start building something new you have to make some assumptions, attempting to solve all possible outcomes and take every corner case into account is just madness. Assumptions are then a part of the way we weigh the pros and cons of different alternatives. These trade-offs might have seemed wise at the time, but hindsight has a funny way of pointing out flaws. Sometimes it’s due to time constraints or business priorities that shifted faster than your favourite show gets cancelled. Other times, it’s simply a lack of experience or foresight that resulted in poor decisions. This isn’t and shouldn’t be construed as criticism in any shape or form, this type of debt is a fact of life and a reason why I argue that documenting your trade-offs in this process is the gold standard. Somewhere down the line someone who isn’t you is going to try to figure out why things work a certain way and they will thank you for it. And you will thank whoever did it in the system you are trying to fix. The software circle of life if you will.
Fixing design debt can be tricky, requiring significant refactoring or even re-architecting parts of the system. It’s like renovating a house while you’re still living in it. You can’t just knock down the walls without considering what might fall apart in the process (like your sanity). The trick is to adopt an incremental approach, improving the design where you can while keeping an eye on the big picture.
The shape of ships
Implementation debt is what most people think of when they hear “technical debt.” It’s the accumulation of rushed code, quick fixes, and “we’ll clean this up later” implementations that never got revisited because, well, later never came. It’s the kind of debt that happens when you’re given an unrealistic deadline and someone utters the classic phrase, “Let’s just get it working for now.” It works. Barely. But it’s hanging together with duct tape, and the duct tape is also made of code that no one quite understands.
A side note, I know you’ve seen the repositories that are full of “WTF?????”-comments and TODOs. It’s easy to sigh and roll your eyes and complain about the kids these days with their gameboys and loud music but the reality is that whoever originally wrote it most likely had someone breathing down their neck, yelling about the need to ship right now. Someone who never got the chance to fix things because once they managed to get what they were building out the door, they got thrown onto some other task. Most of us has been that person, if you haven’t then chances are you’ve been the person yelling.
This kind of debt is often exacerbated by short-term thinking and prioritising quick delivery over long-term maintainability. At the end of the day it ends up being a lot like choosing to drive on a flat tire because you don’t have time to change it—you’ll get where you need to go, but sooner or later you’re going to end up stranded on the side of the road. And you can just hear the banjos playing. The key is to strike a balance. Sometimes, quick and dirty solutions are necessary, but they should come with a plan for when to circle back and do things right.
The matrix is everywhere
Organisational debt is the debt that forms when your system and your company’s structure are out of sync, like a mismatched dance duo where one partner is always a beat behind. This often happens when organisational changes aren’t reflected in the system’s architecture, processes, or responsibilities. The symptoms can be subtle at first—like different teams having conflicting workflows for the same system—but they grow into full-blown dysfunction over time.
Maybe the system’s design still reflects a division between two teams that were merged six months ago, leading to duplicated efforts and a general sense of “does anyone even know who’s in charge of this?” It’s the kind of debt that accrues quietly but can explode into chaos as soon as you try to scale, pivot, or - more frequently - even just make sense of who should be working on what. Addressing organisational debt often requires much, much more than just tweaking code; it may involve rethinking workflows, reassigning ownership, and sometimes even adjusting the company culture to foster better cross-team collaboration. Or challenging leadership to fix the problem.
System bit rot
Knowledge debt is the debt that accumulates when the shared understanding of how a system works erodes over time. This happens because people leave, documentation gets outdated (or wasn’t great to begin with), and the only person who knew how that one obscure subsystem worked is now off living in a remote cabin writing a novel about AI ethics. Without a solid knowledge base, new developers take longer to onboard, existing developers struggle to maintain systems they don’t fully understand, and the system becomes a black box with a growing number of “Do Not Touch” labels.
Tackling knowledge debt requires making documentation a priority and not just something you “get to if there’s time.” It’s also about encouraging knowledge sharing within the team, whether through “lunch and learns,” technical deep dives, or even informal Slack channels where someone can ask, “Why exactly do we use this ancient Perl script?” or "Who is Haskell and why is it handling the financial reporting?" without getting a hundred eyes rolled at them. And the observant reader might also think: “Hey, maybe I could use RAG and an LLM to improve people’s access to information”. Have a cookie.
Check your culture
Cultural debt is the most insidious of them all. It’s not a type of debt that you can see or touch directly, but it manifests in the behaviours and attitudes that encourage other forms of debt to accumulate. It’s the mindset that says, “We don’t have time to refactor, just ship it,” or the attitude that sees documentation as a nice-to-have rather than a necessity. It’s that unspoken understanding that cutting corners is acceptable as long as you make the deadline, even if it means paying a steep price later.
A culture that prioritises speed at all costs will inevitably accumulate more debt than one that balances quick wins with long-term sustainability. Changing this isn’t as simple as putting a “Quality Matters” poster in the breakroom and exclaiming that you have done a shift-left; it requires shifting the organisation’s mindset. The goal should be to foster a culture that values continuous improvement and encourages developers to address debt incrementally, rather than letting it pile up until it becomes a crisis.
Are we bankrupt yet?
Technical debt as it is commonly discussed, is much more than just poorly written code. When we zoom out, we see that system debt encompasses a range of issues that touch upon architecture, processes, knowledge sharing, and even organisational structure and culture. The different types of debt are interconnected, each influencing the other in subtle and not-so-subtle ways. Think of them as interlocking systems that all exert force on the solution you are working on.
To manage system debt effectively, managers, architects and teams need to recognise that it’s not just about paying down code quality debt. It’s about creating a sustainable approach to system development that keeps the whole system healthy. This means regular audits, updating design and vocabulary to reflect current realities, documenting changes, and fostering a culture that doesn’t accept debt as a given, but as something that should be actively managed.
The next time someone says “technical debt,” think of it as a cue to discuss the deeper system debt issues that might be lurking beneath the surface. And if you do find yourself facing an abundance of debt, remember: the sooner you start paying it down, the less likely it’ll be to haunt you in the middle of the night like an intermittent error that corrupts your index. That said, I am going to use the term technical debt moving forward in this section because it makes things easier for everyone.
Dealing with it
Often, the biggest barrier to adopting new processes is the weight of the old ones – specifically, existing complexity and accumulated technical debt. Trying to layer AI assistance or rigorous specification onto a brittle, poorly understood legacy system is unlikely to succeed, much like any attempts to scale a tower of 3D models when your playable character is stuck in a big cauldron. Therefore you most likely will need to do one or more of the following things.
Tackling Existing Debt
Use the new focus on specification and NFRs as an opportunity to understand and address critical technical debt in existing systems. Can AI assist in refactoring or generating tests for legacy code before adding new features?
Modularisation
Break down monolithic systems into smaller, more manageable components with well-defined interfaces. This might mean modularisation or extracting some functionality into separate services or even moving into full blown micro services. Regardless of where you are on your journey, it makes it easier to apply specification-driven approaches to individual pieces.
Improving Observability
Invest in better logging, tracing, and monitoring for existing systems. Understanding current behaviour is essential before trying to change or augment it. Do be aware though that with better observability comes a higher cost and more than one company has suddenly found themselves getting very significant invoices because they didn’t tell everyone that maybe trace and debug logging wasn’t a great idea in a system that handles tens of thousands of requests every second. Just something to keep in mind.
Formalise the Specification Process:
The core of the transformation lies in embracing a more disciplined approach to defining what needs to be built before building it. It has a lot of additional benefits This involves:
Adopting Specification Templates: Rolling out and enforcing the use of standardised templates for NFRs, functional specs, and Synthesised specifications (Chapter 6).
Establishing Review and Approval Workflows: Implementing clear processes for drafting, reviewing, and approving these specification documents.
Investing in Specification Skills: Recognising that writing clear, unambiguous, and testable specifications is a critical skill, and providing training and mentorship (see Section 3).
Making Specs the Source of Truth: Culturally shifting towards treating the approved specification documents as the primary source of truth, guiding development, testing, and even operational readiness.
Rethinking Job Roles and Skill Sets:
As discussed in Chapter 4, roles evolve. The adoption strategy must acknowledge and support this:
Shift from “Code-First” to “Spec-First”: Emphasise the value of design, specification, and validation skills, particularly for senior engineers and leads. Performance reviews and career ladders may need adjustment to reflect this.
Develop Prompt Engineering Skills: Train developers on how to effectively interact with AI tools, crafting prompts that yield accurate and compliant results.
Focus on Validation: Enhance skills in testing, code review (of AI output), and critical analysis to ensure the quality and correctness of AI-assisted work.
Cross-Functional Collaboration: Strengthen collaboration between development, operations, security, and product management around the shared language of specifications.
Incremental Rollout:
Trying to change everything everywhere at once is usually a recipe for disaster. A phased approach is generally more successful:
Pilot Projects: Select one or two suitable projects (perhaps new development or a well-contained refactoring effort) to pilot the new processes and tools.
Build Internal Champions: Identify enthusiastic early adopters (“surgeons,” leads) within the pilot teams to champion the changes and provide feedback.
Learn and Adapt: Use the experience from pilot projects to refine templates, processes, tooling, and training materials.
Gradual Expansion: Roll out the practices to more teams incrementally, providing support and sharing successes (and failures) transparently.
Develop Shared Assets: Build up a central repository of approved NFRs, reusable specification components, and effective prompt libraries based on initial experiences.
Getting there requires a commitment from leadership, a willingness to invest in training and tooling, and a clear strategy for managing the transition incrementally, starting with addressing existing pain points and gradually introducing the new ways of working.
Overcoming Resistance
Introducing significant changes to established workflows, especially ones involving AI and a shift towards more formal specification, will inevitably encounter resistance. This isn’t necessarily malicious; it often stems from genuine concerns, fear of the unknown, ingrained habits, or skepticism based on past failed initiatives. Addressing this resistance proactively and empathetically is crucial for successful adoption.
Common Sources of Resistance & Counters:
Change resistance in engineering organisations doesn’t stem from obstinance, but from a deep-rooted commitment to quality, reliability, and the systems already in place. Engineers have typically invested time and care into building processes that work, and sudden shifts can feel like threats to stability rather than opportunities for improving both their working environment as well as the system. A non-judgemental approach begins by recognising this context and treating resistance as a signal worth listening to—not a barrier to bulldoze. Instead of positioning the new way of working as inherently better, it helps to frame it as something to test, validate, and refine together. This shifts the conversation from compliance to collaboration and builds psychological safety around uncertainty.
Equally important is respecting the tacit knowledge already embedded in the current system. When teams feel heard and see their concerns reflected in the rollout plan, they’re more likely to participate meaningfully. Invite feedback early, and make it clear that critique is not only welcome but necessary for success. By focusing on shared goals—like reducing cognitive load, increasing velocity without sacrificing quality, or enabling more ownership—you can co-create a narrative that feels additive rather than corrective. Change, then, becomes something the team is doing for itself, not something being done to it.
There are common themes though that I have tried to collect here with suggestions on how to counter them.
Myth: “LOSS OF CONTROL / AI will replace us."
Reality: As we’ve emphasised, this is about augmentation, not replacement. Humans remain in control of specification, validation, and critical decision-making. The goal is to elevate developers to focus on higher-level tasks, making their unique human skills (creativity, critical thinking, system design) more valuable, not less. AI handles the toil, humans handle the strategy.
Counter: Frame AI as a powerful “copilot” or “assistant” (Chapter 4) that amplifies developer capabilities. Highlight how it automates boring, repetitive tasks, freeing up time for more interesting work. Emphasise the need for human oversight and validation. Show, don’t tell to get over the trust barrier. And be willing to go first.
Myth: "This is slower / Too bureaucratic."
Reality: While writing detailed specifications upfront requires an initial investment of time, it often saves significant time downstream by reducing ambiguity, rework, debugging, and lengthy bug-fixing cycles. The Design → Test Gen → Code Gen → Test workflow aims for faster validated delivery, not just faster typing of initial code.
Counter: Use pilot projects to demonstrate the end-to-end benefits. Track metrics beyond just code generation speed, focusing on reduced bug rates, faster QA cycles, and improved maintainability. Show, don’t just tell. Frame specification not as bureaucracy, but as essential communication and risk mitigation.
Myth: "AI can’t do real coding / It’s just for simple stuff."
Reality: AI capabilities are rapidly evolving. While it might struggle with highly novel or complex algorithmic breakthroughs today, it’s already proficient at generating significant amounts of boilerplate, implementing standard patterns, writing tests, and translating between languages – tasks that consume a large portion of developer time. Furthermore, the focus shifts: the “real” engineering work becomes the specification, design, and validation, which AI assists rather than performs autonomously.
Counter: Showcase concrete examples from pilot projects where AI successfully handled non-trivial tasks based on good specifications. Focus on how AI enables developers to tackle more complex problems by handling the routine parts.
Myth: "NO formal specs Please; we’re Agile!"
Reality: Agile doesn’t mean “no documentation” or “no planning.” It means adapting to change and delivering value incrementally. Clear specifications (even if they evolve) are essential for communication and shared understanding, especially when collaborating with AI agents that cannot infer intent like humans can. Structured specs enable agility by providing clear targets for each iteration and reducing ambiguity-driven rework.
Counter: Explain how clear specs support agile principles like sustainable pace (less rework), technical excellence, and effective communication. Show how the “Design → … → Final Specs” loop incorporates iterative refinement.
Remember Human Nature
Fear of Learning New Skills: Developers may be comfortable with their current tools and workflows and hesitant to learn specification writing, prompt design, or new validation techniques. This isn’t strange at all, we like to be comfortable. We, as humans, like the familiar and fear the unknown, If someone wants comfort food, you shouldn’t try to bring them something they’ve never tried before, that isn’t go to land well.
Counter: Provide excellent training, resources, and mentorship (Section 3). Create a psychologically safe environment where experimentation and learning are encouraged. Highlight how these new skills are becoming increasingly valuable in the industry. Frame it as professional development, not just a process change.
Strategies for Overcoming Resistance:
Executive Sponsorship: Clear, consistent support from leadership is essential to signal the importance of the change.
Involve Teams Early: Don’t impose changes from the top down. Involve developers and leads in defining the new processes, selecting tools, and running pilot projects. Ownership breeds acceptance.
Communicate the “Why”: Clearly articulate the motivations (Chapter 2) and benefits (faster delivery of quality, less toil, focus on interesting work) for both the organisation and individual developers.
Start Small & Show Value: Use pilot projects to demonstrate tangible benefits and build momentum. Success stories are powerful persuaders.
Provide Training & Support: Invest heavily in training, documentation, and readily available support for the new tools and processes.
Celebrate Early Wins: Publicly recognise teams and individuals who successfully adopt the new practices.
Be Patient and Persistent: Cultural change takes time. Expect setbacks, listen to feedback, adapt the approach, but remain persistent in pursuing the long-term vision.
Overcoming resistance requires understanding the underlying concerns, communicating clearly, demonstrating value, providing support, and involving people in the change process.
Scaling AI Education
Successfully adopting AI-augmented development isn’t just about changing processes or installing tools; it’s fundamentally about equipping your people with new skills and a new mindset. You can have the best specifications and the most advanced AI agents, but if your developers don’t know how to effectively write those specs, interact with the agents, or validate the results, the transformation will stall. Scaling education is therefore a critical pillar of any adoption strategy.
What key areas should training focus on?
Specification Writing: This is perhaps the most crucial new skill. Developers need to learn how to:
Translate business needs and user stories into clear, unambiguous, and testable functional requirements (using templates like spec-template.md).
Identify, define, and document relevant Non-Functional Requirements (using nfr-template.md), including defining clear verification criteria.
Synthesise these into comprehensive component specifications (like Synthesised-specification.md).
Use precise language (including RFC 2119 keywords) and structure to minimise ambiguity.
Understand the importance of linking functional specs to NFRs.
Training should involve workshops, examples, and practice sessions focused on writing high-quality specifications.
Structured Thinking & Decomposition: Related to specification writing is the ability to think structurally about problems and break them down logically. This helps in decomposing epics into tasks and defining clear inputs, outputs, and constraints for each step – essential for both manual execution and guiding AI agents.
Prompt Engineering: Interacting effectively with LLMs and AI code generation tools is a skill in itself. Training should cover:
Understanding how different AI models work (at a high level).
Crafting clear, concise, and context-rich prompts.
Providing effective examples (few-shot prompting).
Defining constraints and desired output formats.
Iteratively refining prompts based on AI output.
Understanding potential biases or failure modes of AI models.
This might involve sharing best practices, creating internal prompt libraries, and hands-on labs.
AI Output Validation & Critical Analysis: Developers must not blindly trust AI-generated code or artefacts. Training needs to emphasise:
Techniques for critically reviewing AI code for correctness, security vulnerabilities, performance issues, and adherence to standards.
The importance of rigorous testing (unit, integration, performance) specifically targeting AI-generated components.
Debugging strategies for code that the developer didn’t write themselves.
Understanding the limitations and potential pitfalls of current AI technology.
Using New Toolchains: Training on the specific AI tools, IDE integrations, specification repositories, and CI/CD pipelines being adopted is essential for smooth workflow integration.
Scaling Education
This is a complex subject and I can, in good conscience, only provide some generic pointers. I would however like to emphasise the need for and benefits of mentorship and coaching. This actually goes both ways. If you reach out to the organisation you work in today, you are likely to find some very forward leaning people with very varied levels of experience. Let them show you what they’re doing. And learn by doing. There’s no real map, in as much as I have tried to provide some pointers. You, like the JRPG players of the 1980s, have to draw your own. And then help guide the organisation forward.
Formal Training Sessions: Workshops, webinars, and dedicated training modules on specification writing, prompt engineering, etc.
Internal Documentation & Knowledge Bases: Create and maintain internal wikis or portals with templates, examples, best practices, and tool guides.
Mentorship & Coaching: Pair experienced engineers (“surgeons,” leads) who have mastered these skills with more junior team members. Encourage peer learning and code/spec reviews focused on these new areas.
Communities of Practice: Establish internal groups focused on AI in development, specification best practices, or prompt engineering, where developers can share knowledge and experiences.
Pilot Team Evangelism: Leverage the experiences and successes of pilot teams to create case studies, demos, and internal talks to educate and inspire other teams.
Integrate into Onboarding: Include training on specification-driven development and AI tools as part of the standard onboarding process for new hires.
Continuous Learning: AI technology evolves rapidly. Foster a culture of continuous learning through lunch-and-learns, access to online courses, and encouraging experimentation.
Investing in education demonstrates a commitment to supporting developers through this transition. It empowers them with the necessary skills to thrive in the AI-augmented era, turning potential resistance into engaged participation and ensuring the organisation can fully realise the benefits of these new ways of working.