02 | Let's Talk About DDRs: The Missing Piece in AI-Driven Development

After many months of working with AI coding assistants, I've come to realise that ADRs (Architectural Decision Records) aren't just nice-to-have documentation anymore. They're **essential context** for AI-driven development. ## The AI Context Problem **AI makes architectural consistency harder, not easier**. When you ask an AI to write code, it's like giving a kid a blank canvas. It doesn't know the rules, the constraints, or the established patterns. It only has the context you've given it and whatever it reads from the codebase using its tools. To make progress, the AI fills in the gaps using assumptions based on its training data. The assumptions it makes are generally fine, but here's the thing - they won't always be the same assumptions it made last time, and those assumptions won't always match the ones you've already made. Another issue with using AI is that it's hyper-focused on completing the task at hand. It won't focus on making maintainable choices. If it needs a method to calculate the distance between two points, it'll either inline the code or create a new method. It has no idea there's already an established pattern of using a `DistanceCalculator` class with a `CalculateDistance` method. It has no curiosity to check whether an existing method or class could be reused. Which means you end up with a lot of duplication and inconsistency, with no hope of maintaining the code over a long time horizon. When an AI agent starts coding without context, it makes assumptions. It might: - Choose patterns that conflict with your architecture - Use libraries you've deliberately avoided - Implement solutions you've already rejected - Violate security or performance constraints you've established - Duplicate work you've already done elsewhere - Use variable names and property names that don't match your conventions - Reimplement solutions that are already implemented elsewhere Even decisions that seem "obvious" to you and me, given the current project, are completely invisible to the AI. That authentication pattern you chose after weighing three alternatives? The AI doesn't know you rejected the other two. That database design you settled on after considering performance trade-offs? The AI starts fresh every time. Without explicit guidance, even the best AI will just fall back to generic patterns that might not fit your specific project needs. ## ADRs: The Missing Context Layer At work, ADRs are invaluable for driving conversations and helping the team align. In my experience, the problem is that after six months, no one remembers that ADR even exists. The historical record proves useful when working on a new decision, but most of the time ADRs just get buried under a pile of other ADRs. What I discovered (almost by accident) is that for coding agents, ADRs aren't just historical records anymore. They're active constraints that can shape every piece of generated code. ADRs capture the *why*, not just the *what*. For AI agents, this context is gold - it's exactly what they need to understand how to extend the codebase in the right direction. ### The ADR/DDR Index I maintain an ADR/DDR index file that makes all decisions discoverable by AI. `docs/ddrs/CLAUDE.md` This file contains summaries of all decisions with links. ## Beyond ADRs After a few months of doing this, I started wanting to document things that weren’t strictly architecture-related. I found myself creating ADRs for decisions that could in no way be called architectural. I kept this up for a while, because the ADR index worked so well: the AI could dive deep into relevant subjects and topics, and it was genuinely useful to have these non-architectural constraint documents. Ultimately, though, I decided a change of name was in order: Design Decision Records (DDRs). ## Making DDRs Work with AI The key is treating DDRs as **AI contracts** rather than just documentation. I structure mine with: - Context - Decision - Rationale - Implementation: bullets - Constraints & Rules: Bullets/lists - Consequences: Bullets or short paragraphs - Compliance: Bullets ## My DDR Creation Process I've developed a prompt for creating high-quality DDRs. Here's the template I use:

Click to view my /create-ddr slash command
```text // title:create-ddr.md // wrap:true # Prompt: Create Design Decision Record (DDR) Design Decision Record is like an ADR but goes further than just architecture to all parts of the software You are an expert technical architect tasked with creating a comprehensive, high-quality Design Decision Record (DDR) within the [Project Name] project following established patterns and best practices. ## DDRs as AI Contracts DDRs in this project are not just historical documentation-they are **active constraints** that shape every piece of generated code. They serve as the primary interface between human intent and AI execution. Every undocumented architectural assumption becomes a potential failure point when AI generates code. Without explicit guidance in DDRs, AI agents fall back to generic patterns that may conflict with established architecture. Your DDRs must provide clear, actionable guidance that future AI agents can follow to maintain architectural consistency. ## 1. Research Phase (MANDATORY) Before creating any DDR, you MUST conduct thorough research to ensure quality and alignment: ### Essential Research Steps - **Check Related DDRs**: Examine individual DDR files in `C:\git\[Project Name]\docs\ddrs\` that might relate to your decision. Determine if you should update an existing DDR or create a new one - **Study Project Conventions**: Reference main `CLAUDE.md` and component-specific `CLAUDE.md` files to understand established patterns - **Analyse Architecture Context**: Review existing vertical slicing, domain-driven design, and CQRS patterns - **Understand Dependencies**: Identify how the proposed decision affects other system components - **Research Industry Best Practices**: Investigate current industry standards and alternative solutions - **Validate Problem Statement**: Ensure the problem is well-defined and actually needs solving ### Template Location Use the official template: `C:\git\[Project Name]\docs\ddrs\template.md` ## 2. User Engagement Questions Before writing the DDR, engage with the user to clarify critical aspects through structured questioning: ### Problem Definition & Context Questions - **Problem Statement**: What specific problem or challenge is this DDR intended to solve? - **Business Impact**: What are the concrete symptoms or business consequences of this problem? - **Scope Assessment**: What parts of the system (backend, frontend, specific services, infrastructure) are affected? ### Requirements & Constraints Questions - **Success Criteria**: What measurable outcomes would indicate this decision was successful? - **Non-Negotiable Constraints**: Are there technical, business, regulatory, or timeline constraints that cannot be compromised? ### Solution Exploration Questions - **Alternative Solutions**: What other approaches have been considered? What are their specific pros and cons? - **Implementation Complexity**: What is the estimated effort and risk level for each alternative? - **Reversibility**: How easy would it be to change this decision in the future? - **Dependencies**: What other systems, technologies, or decisions does this depend on or influence? ## 3. DDR Creation Guidelines ### Content Structure - Write with Exceptional Quality **CRITICAL: INFORMATION DENSITY OVER VERBOSITY** DDRs must be **maximally information-dense** to preserve AI context windows. Every word must earn its place. The goal is the **least number of words to convey the most information**. Concise, precise, actionable. **CRITICAL: DDRs MUST BE TIMELESS** DDRs document **what the decision is** and **why it's good**. NEVER include migration details, transition plans, or "how we get from A to B" content. These temporal details become irrelevant once complete and don't stand the test of time. Focus exclusively on: - The current architectural decision - Why it was chosen over alternatives - What the constraints and patterns are - How to implement it correctly Migration belongs in tickets, not architecture documentation. **Prose vs Bullets Decision:** - **Context, Decision, Rationale**: Flowing prose (1-3 concise paragraphs each) - **Implementation, Constraints & Rules, Consequences, Compliance**: Use bullets, lists, or tables - whatever format conveys information most efficiently **Length Targets:** - Context: 1-2 paragraphs (max 200 words) - Decision: 1-2 paragraphs (max 150 words) - Rationale: 2-3 paragraphs (max 300 words) - Implementation: Code examples + bullets (max 250 words) - Constraints & Rules: Bullets/lists (max 200 words) - Consequences: Bullets or short paragraphs (max 200 words) - Compliance: Bullets or 1-2 paragraphs (max 150 words) **Target DDR length: ~1200 words maximum** (smaller is better if complete) #### Context Section **CONCISE PROSE**: Establish the problem space efficiently. What's the core problem? What's the current state? What forces are at play (performance vs maintainability, cost vs capability)? Why does this matter to the business and users? Every sentence must add new information. #### Decision Section **CONCISE PROSE**: State what we're doing, clearly and unambiguously. What's the primary decision? What's in scope, what's out? What are the key components? How does this integrate with existing architecture? #### Rationale Section **CONCISE PROSE**: Why this decision? Present 2-3 alternatives considered and **why each was rejected** (prevents AI re-evaluation). What were the decision criteria (performance, cost, risk, maintainability)? What trade-offs did we make? Reference industry practices if relevant. Connect to broader architectural principles. #### Consequences Section **BULLETS PREFERRED**: List positive/negative impacts with measurable outcomes. Risk mitigation. Example: **Positive:** Benefit 1, Benefit 2 **Negative:** Downside 1 with mitigation, Downside 2 with risk mitigation #### Constraints & Rules Section (REQUIRED) **BULLETS REQUIRED**: Actionable constraints AI agents follow without interpretation. - **Always Patterns**: Must always be followed (e.g., "Always use `Result` for operations that can fail") - **Never Patterns**: Must never be used (e.g., "Never use `DateTime.Now`; always use `TimeProvider`") - **Conditional Rules**: Context-specific (e.g., "When creating aggregate, validate through `DomainAssert`") - **Code Patterns**: ✅ right way / ❌ wrong way examples #### Implementation Section (REQUIRED) **CODE + BULLETS**: Show pattern through code examples. Use bullets for architecture fit, integration points, configuration, testing. #### Compliance Section **BULLETS PREFERRED**: Validation method, what needs updating. ### Additional Sections You are encouraged to add other sections beyond the template if they provide value to the DDR. Examples: - **Performance Considerations**: Specific performance implications and benchmarks - **Security Implications**: Security analysis and mitigation strategies - **Examples**: Real-world usage examples from the codebase ### Naming Conventions - **Filename**: Use sequential numbering (check docs\ddrs\CLAUDE.md for next number) + concise description (**max 5 words**, snake_case) - Examples: `ddr034_nunit_testing.md`, `ddr035_oauth_providers.md` - **Title**: Clear and descriptive, focusing on the decision rather than the problem - **Date**: Always include current date in YYYY-MM-DD format - **Updated Date**: Add when making significant changes to existing DDRs ### Reference Integration - **Link Related DDRs**: Reference existing DDRs in rationale (e.g., "This aligns with DDR-018: Use RabbitMQ") ### CLAUDE.md Update - **Update CLAUDE.md**: After creating or updating a DDR, ensure a concise, information-dense summary is added or updated in `C:\git\[Project Name]\docs\ddrs\CLAUDE.md`. This file serves as a quick reference for LLMs and should be kept up-to-date with all DDRs. ## 4. Update vs Create New DDR ### When to Update an Existing DDR DDRs are living documents that evolve with the codebase. Update an existing DDR when: - **Refinement**: Adding clarity, examples, or implementation details to an existing decision - **Evolution**: The core decision remains but implementation details have changed - **Correction**: Fixing inaccuracies or updating based on learned experience - **Extension**: Adding new consequences, considerations, or compliance requirements ### When to Create a New DDR Create a new DDR when: - **Fundamentally Different Decision**: The approach is conceptually distinct from existing DDRs - **New Problem Domain**: Addressing a completely different architectural concern - **Separate Concern**: The decision stands independently and doesn't modify existing decisions ### Update Process 1. **Read Existing DDR**: Understand the current decision and rationale thoroughly 2. **Use Git History**: Review git history to understand how the DDR evolved 3. **Make Inline Updates**: Edit the DDR directly, improving and extending sections as needed 4. **Update Date**: Add an "Updated" line below the original date: `**Updated:** YYYY-MM-DD` 5. **Commit with Clear Message**: Explain what changed and why in the commit message 6. **Update CLAUDE.md**: Ensure the summary reflects the current state ### Version History Git serves as the version history system for DDRs. Never maintain version history within the DDR file itself - use `git log` and `git diff` to see how decisions evolved over time. ## 5. Quality Assurance Checklist Before finalising the DDR, verify every aspect meets high-quality standards: ### Research & Foundation - [ ] Thorough research of existing DDRs completed with no conflicts identified - [ ] All user engagement questions asked and answered comprehensively - [ ] Industry best practices researched and referenced where applicable - [ ] Alternative solutions properly evaluated with objective criteria ### Content Quality - [ ] **INFORMATION DENSITY**: Every word earns its place - maximum information per word - [ ] **LENGTH TARGET**: Concise, ideally under 1200 words - [ ] **Prose ONLY for Context, Decision, Rationale** - everything else uses bullets/lists/code - [ ] **Constraints & Rules section included** - explicit Always/Never patterns - [ ] **Rejected alternatives documented** with reasons why - [ ] **Code examples** with ✅/❌ comparisons - [ ] **Actionable, not academic** - clear patterns AI can follow ### Technical Integration - [ ] Aligns with [Project Name]'s vertical slicing architecture - [ ] Follows established patterns (DDD, CQRS, Result pattern, IPulse) - [ ] Code examples are accurate and follow project conventions - [ ] Integration with existing systems properly considered ### Documentation Standards - [ ] Template structure followed completely with all required sections - [ ] Related DDRs properly referenced with correct links - [ ] Filename follows naming conventions (sequential number + max 5 words) - [ ] Date field present (with Updated field if this is a modification) - [ ] CLAUDE.md updated with concise summary for AI context ## 6. Task Execution Protocol Execute the following steps systematically to create exceptional DDRs: ### Step 1: Foundation Research (MANDATORY) 1. **Study Architecture**: Review the ddr docs\ddrs\CLAUDE.md files to understand current patterns and conventions 2. **Check for Existing DDRs**: Determine if you should update an existing DDR or create a new one 3. **Validate Problem**: Ensure the problem is real, well-defined, and worth solving ### Step 2: Structured User Engagement 1. **Ask Comprehensive Questions**: Use the structured questioning framework to gather complete information 2. **Clarify Requirements**: Ensure success criteria, constraints, and stakeholder impacts are understood 3. **Explore Alternatives**: Work with user to identify and evaluate multiple solution approaches ### Step 3: Create High-Quality DDR 1. **Follow Template**: Use content structure guidelines - prose for Context/Decision/Rationale, bullets for Implementation/Constraints/Consequences/Compliance 2. **Document Rejected Alternatives**: Explain why each alternative was dismissed (prevents AI re-evaluation) 3. **Include Code Examples**: Show ✅ right way / ❌ wrong way patterns 4. **Be Information-Dense**: Maximum information, minimum words ### Step 4: Complete Documentation Updates 1. **Update CLAUDE.md**: Add or update concise summary for AI context and quick reference 2. **Cross-reference Related DDRs**: Ensure proper linking and relationship documentation 3. **Verify File Naming**: Follow sequential numbering and naming conventions (new DDRs only) 4. **Update Date Field**: Add "Updated" date if modifying an existing DDR ### Step 5: Quality Validation 1. **Self-Review Against Checklist**: Verify all quality criteria are met 2. **Architecture Alignment**: Ensure decision fits with vertical slicing, DDD, and CQRS patterns 3. **Implementation Feasibility**: Verify proposed solution is technically sound and achievable ## Final Guidelines DDRs are living documents that evolve through git-tracked updates. They serve as current truth about architectural patterns and guide implementation teams. **Critical Success Factors:** - Maximum information density - every word earns its place (critical for AI context windows) - Document rejected alternatives and WHY (prevents AI re-evaluation) - Provide ✅/❌ code examples AI agents can copy - Quality ≠ verbosity - information-dense, not word-dense --- - Remember: we don't care about what it used to be, and we don't care about implementation steps. We only care about documenting the decision and the details around it. - Don't show source code in the DDR unless absolutely necessary. - We want good flowing text, not walls of lists. Some lists are fine, but for the most part we want flowing prose. ```

Click to view my template.md file
```text // title:template.md // wrap:true # DDR-XXX: [Title - Focus on the Decision, Not the Problem] **Date:** YYYY-MM-DD **Updated:** YYYY-MM-DD _(only include if this DDR has been modified)_ --- ## Context **[WRITE AS CONCISE PROSE - max 200 words]** Establish the problem space efficiently: - What's the core problem? - What's the current state? - What forces are at play (performance vs maintainability, cost vs capability)? - Why does this matter to business and users? Every sentence must add new information. --- ## Decision **[WRITE AS CONCISE PROSE - max 150 words]** State what we're doing, clearly and unambiguously: - What's the primary decision? - What's in scope, what's out? - What are the key components? - How does this integrate with existing architecture? --- ## Rationale **[WRITE AS CONCISE PROSE - max 300 words]** Why this decision? Address: - **Alternatives Considered**: Present 2-3 alternatives with pros/cons - **WHY EACH WAS REJECTED**: Critical - prevents AI re-evaluation of dismissed options - **Decision Criteria**: Performance, cost, risk, maintainability - **Trade-offs Made**: What we're optimising for vs sacrificing - **Industry Practices**: Reference if relevant - **Architectural Alignment**: How this connects to broader principles --- ## Constraints & Rules **[BULLETS/LISTS REQUIRED - max 200 words]** Actionable constraints AI agents follow without interpretation: **Always:** - [Must always be followed - e.g., "Always use `Result` for operations that can fail"] **Never:** - [Must never be used - e.g., "Never use `DateTime.Now`; always use `TimeProvider`"] **When [Condition]:** - [Context-specific rules - e.g., "When creating aggregate, validate through `DomainAssert`"] **Code Patterns:** -`-`-`csharp // ✅ Right way [Example showing correct pattern] // ❌ Wrong way [Example showing anti-pattern to avoid] -`-`-` --- ## Implementation **[CODE EXAMPLES + BULLETS - max 250 words]** Show the pattern through code: -`-`-`csharp // Primary code example demonstrating the decision [Complete, copy-paste-ready example showing all layers if applicable] -`-`-` **Architecture Integration:** - How this fits with vertical slicing, DDD, CQRS patterns **Configuration:** - Required updates to settings, Docker, infrastructure **Testing:** - How implementation will be validated --- ## Consequences **[BULLETS PREFERRED - max 200 words]** ### Positive - [Specific benefits with measurable outcomes where possible] ### Negative - [Honest assessment of downsides, risks, additional complexity] - [Risk mitigation strategies] --- ## Compliance **[BULLETS PREFERRED - max 150 words]** **Verification:** - How compliance will be validated ```
## The Compound Effect The real power emerges when you have a collection of well-documented decisions. Those assumptions you could safely leave as implicit with human developers? They need to become explicit requirements for AI. The "obvious" choices that you never thought to document? They need to be written down. People who say "the code is the documentation" (meaning you don't need any other documentation) are, I've come to realise, mistaken - especially in the LLM era. There's so much context around *why* we do things a certain way that simply can't be captured in code alone. Documentation kept in a separate wiki, away from the codebase, always fails to keep up with the code - and it's completely opaque to LLMs. I've found DDRs exponentially more valuable with AI. Unlike the vast majority of pre-LLM ADRs that were only read within weeks of publication, LLM-oriented DDRs provide value every day. They're referenced constantly and actively shape how code gets written. With a collection of well-documented decisions, AI agents can: - **Avoid conflicting patterns** by understanding the full decision context - **Suggest better solutions** based on established project constraints - **Maintain consistency** across different parts of the system - **Stop re-solving already-solved problems** - they understand what was tried and why it was rejected - **Act independently for longer** - as they have access to important context when they need it ## Lessons Learned: Common Pitfalls I've made plenty of mistakes with DDRs that cost me time. Here's what I learned: ### Writing DDRs Too Dense for AI My first DDRs read like academic papers - dense paragraphs full of technical jargon and architectural theory. Wasting valuable context window space. What works far better: clear sections, bullet points of "always do this" and "never do that", and concrete patterns. ### Not Updating DDRs When Decisions Change When a decision changes, you need to be diligent about updating the DDR. It's part of the work - not something to defer until later. Since these DDRs are for AI, I don't supersede the old DDR with a new one. That approach creates long chains of DDRs that the AI has to read, wasting context for no good reason as the AI doesn't need to know about history. Instead, I update the existing DDR to reflect the new decision and make no reference to the old one. If I'm ever curious about a previous decision, I can always check git history. History is useful when questioning an ADR and deciding to change the decision or make new decisions, it's not necessary for implementation. This way of thinking for me exemplifies the position I think humans will occupy moving forward. AI as implementers and the longer term strategic thinking is where we operate. ## Discovering Your Implicit DDRs **You almost certainly already have design/architectural decisions - they're just not documented yet.** Even on greenfield projects, if you're a developer you have certain ways you like to work whether that be TDD, DDD or just what packages you are familiar with. Instead of writing DDRs from scratch, I now spend AI compute cycles upfront to analyse my codebase and extract the patterns I'm already using. Think of it as burning compute once to crystallise those insights, then reusing them forever. Here's my workflow: ### 1. Point AI at Your Codebase ```text "Analyse the authentication implementation across this codebase. What patterns do we consistently use? What alternatives did we avoid? What constraints are implied by the current implementation?" ``` ### 2. Have AI Draft the DDR (using the above slash command (prompt)) ```text "Based on your analysis, draft a DDR documenting our authentication approach. Include the decision, rationale, alternatives we're NOT using, and code examples." ``` ### 3. Review and Refine The AI does the heavy lifting of extracting patterns from code, but you add the crucial "why" - the context that isn't in the code. Why did you choose this approach? What were the business drivers? What alternatives did you actively reject? This approach is especially valuable for existing projects. It lets you capture the design/architectural wisdom that's currently locked in your head and in the code patterns, making it explicit and reusable. ## Start Small You don't need 42 DDRs on day one. Start with the decisions that matter most: 1. **Authentication & Security** - How do you handle user sessions? 2. **Error Handling** - How do you manage and propagate errors? 3. **Data Access** - What's your database interaction pattern? 4. **API Design** - What are your REST/GraphQL conventions? 5. **Testing Strategy** - How do you structure and organise tests? For existing projects, let the AI discover these patterns from your code. For new projects, document decisions as you make them. ## The Documentation-First Future After months of working with AI, I've realised something fundamental has changed: **documentation isn't just helpful anymore - it's the primary interface between human intent and AI execution**. I've watched DDRs transform AI agents from generic code generators into project-aware partners that understand and respect my constraints. They prevent the AI from re-evaluating design/architectural decisions from scratch every time, sparing me from watching it choose alternatives I'd already considered and rejected and the rework that follows. What design/architectural decisions in your project would benefit from being documented as DDRs? Start there, and see how much more aligned your AI assistance becomes. In my [next post](/blog/03-let-your-ai-load-its-own-context), I'll show you how to let the AI load its own context automatically - no more manually specifying files in every prompt.