Gradual Migration — Going from 0 to DDD Without Stopping the Train

You don't need a monolith to have a mess.

Some of the worst codebases I've worked with weren't monoliths at all. They were a patchwork of n8n workflows, Supabase edge functions, Azure Functions, a React app talking to three different backends, and a payment system held together by Playwright browser automation because the ERP had no API. Each piece made sense when it was built. Together, they're a nightmare to reason about.

This is reality for a lot of teams, especially startups that moved fast and survived. The code worked. The business grew. And now every new feature feels like defusing a bomb.

The Old Trade-off

Domain-Driven Design was always the answer on paper. Bounded contexts, aggregates, ports and adapters, application services — the whole thing gives you a codebase that maps cleanly to business concepts and is ready to evolve.

But there was a cost. A real one.

Creating a proper DDD structure means a lot of files. Interfaces, implementations, value objects, domain events, repository contracts, application services, DTOs — for a single feature you might touch fifteen files across five directories. For an enterprise team with six months of runway, that's fine. For an MVP? It felt like building a cathedral to sell lemonade.

So teams skipped it. They went straight to "make it work" and promised themselves they'd refactor later. Later never came. The patchwork grew. And here we are.

What Changed

AI coding agents changed the economics completely.

Here's the workflow now: you sit down with domain knowledge — the actual business rules, the edge cases your team discovered over months of production — and you write a spec. Not code. A spec. "When a rental is returned late, calculate the penalty based on the rate tier and notify billing. If the customer has a deposit, deduct from there first."

That spec becomes clean, well-structured DDD code in minutes. Not hacked-together code. Proper code — with interfaces, with clear boundaries, with tests. The kind of code that would have taken a developer two days of careful architecture work.

The multiplication of files that used to make DDD painful? The AI doesn't care. Creating ten files for a bounded context costs the same as creating one. The cognitive overhead of maintaining clean separation between layers? It's handled. You describe the domain, the agent builds the structure.

Why This Matters for MVPs

This flips the old logic on its head.

Before: "We can't afford DDD for an MVP. Ship fast, refactor later."

Now: "We can't afford NOT to use DDD for an MVP. The setup cost is near zero, and when we need to iterate, everything is already in the right place."

Think about what happens when your MVP finds product-market fit and suddenly you need to:

  • Add a payment provider
  • Support a new country with different tax rules
  • Integrate with a partner's API
  • Handle a business rule that contradicts three existing assumptions

With DDD in place, each of these is a contained change. You add an adapter, you extend a domain service, you create a new bounded context. The blast radius is small and predictable.

Without it? You're back to defusing bombs.

The Practical Path

You don't migrate everything at once. You don't stop the train.

Pick one bounded context — the part of your system where the business rules are most complex or most likely to change. Extract it properly. Let the AI do the heavy structural work while you focus on the domain knowledge that only you have.

Once that first context is clean and tested, the contrast with the rest of the codebase becomes obvious. The next migration gets easier because you have a pattern. The third one is almost mechanical.

The key insight is this: you are the domain expert, the AI is the architect. You know that a rental return in the Dominican Republic involves a different inspection flow than one in São Paulo. The AI knows how to express that as a strategy pattern inside a domain service with proper dependency injection. Together, you move fast without creating debt.

The Hidden Multiplier: Testability

There's another angle that doesn't get enough attention. When AI writes your code, testability isn't a nice-to-have — it's your safety net.

A well-structured DDD codebase is inherently testable. Domain logic is pure. Dependencies are injected. Boundaries are explicit. That means every piece of AI-generated code can be verified automatically before it touches production. The agent writes the feature, writes the tests, and you can see immediately if the behavior matches what you specified.

Without that structure? The AI generates code that "looks right" and maybe even runs — but you have no systematic way to verify it does what you think it does. You're trusting vibes instead of tests.

And here's the second punch: a well-defined architecture makes the AI less likely to hallucinate in the first place. When there are clear patterns, established conventions, and explicit interfaces, the AI has guardrails. It knows where things go. It follows the existing structure instead of inventing one. A clean codebase constrains the AI in exactly the right way — it reduces the surface area for creative mistakes.

A messy codebase does the opposite. It gives the AI maximum freedom to be wrong in maximum ways.

The Bottom Line

DDD's cost was never conceptual. Everyone understood why clean architecture was better. The cost was practical — the sheer effort of setting it all up and maintaining the discipline across a team.

AI agents eliminated that cost. The discipline is encoded in the spec. The structure is generated. The tests come for free. And the architecture itself acts as a guardrail that keeps the AI honest.

If you're starting something new today, there's no excuse not to start clean. And if you're sitting on a patchwork of microservices, functions, and workflows that technically work but nobody wants to touch — you can fix it gradually, one bounded context at a time, without stopping anything.

The train keeps running. You just replace the tracks underneath it, one section at a time.


Omar Díaz Peña builds autonomous development systems and writes about the messy reality of AI in production.

← Back to Blog