AI-Powered Refactoring: Modularising Code with Codex 5.4

Refactoring a codebase into well-defined modules is one of those tasks every developer knows is valuable—but rarely prioritises.

It’s cognitively heavy, time-consuming, and easy to get wrong. Doing it properly requires holding a large amount of context in your head: dependencies, responsibilities, side effects, and hidden coupling.

With Codex 5.4, something has genuinely changed.


A quick note on timing (and why this post exists)

In my previous post, The Joy of Codex, I wrote about my experience using Codex 5.3 to improve my codebase.

Ironically, that post was almost outdated by the time I finished writing it.

A new version—Codex 5.4—was released, and the difference is significant.


My setup: a small but real codebase

This isn’t a massive system. It’s a relatively small project:

  • A single JAR
  • A tightly coupled structure
  • Reasonable logical separation via packages and interfaces—but not true modularisation

Using Codex 5.3, I managed to extract one component—babylon-table—into its own module. That was already a meaningful improvement.

But it still felt like manual progress: I was driving the decomposition, and Codex was assisting with execution.


What changed with Codex 5.4

With Codex 5.4, I approached the same codebase differently.

Instead of guiding it step-by-step, I asked it to analyse the entire project and propose modularisation opportunities.

What it returned went well beyond incremental refactoring:

  • Proposed module boundaries based on dependency structure
  • Identified implicit responsibilities across packages
  • Suggested separations that reduced coupling
  • Outlined a practical, incremental path to get there

For example, it identified that AWS storage concerns were leaking across the codebase, with multiple components directly depending on AWS-specific logic.

It proposed introducing a storage abstraction, and isolating all AWS-specific implementations behind dedicated modules.

This resulted in:

  • A stable interface for storage operations
  • AWS dependencies confined to a small, well-defined boundary
  • The rest of the system decoupled from infrastructure concerns

That’s the kind of structural improvement that’s easy to defer during incremental refactoring—but has a disproportionate impact on long-term maintainability.

It wasn’t just moving code—it was reasoning about architecture.


The surprising part

Work at this level is typically:

  • Slow
  • Error-prone
  • Dependent on deep, system-wide understanding

And yet, Codex handled it:

  • Very quickly
  • Very effectively
  • And, in my testing—without introducing obvious regressions

That last point is what stood out most.

Because refactoring at this level almost always comes with some breakage. That’s usually the trade-off.


The result

The codebase now has a much clearer separation of concerns, enforced through module boundaries and dependencies.

Dependency graph showing the Babylon Java modules and the direction of their dependencies

Dependency Graph for Babylon Code Modules

Arrow direction: module depends on target

One could argue that this level of modularisation is excessive for a small codebase, especially from a deployment perspective.

But small codebases rarely stay small.

Establishing clear boundaries early tends to pay off over time—and is significantly harder to retrofit later.


A shift in how refactoring happens

What I experienced moving from 5.3 → 5.4 wasn’t just an improvement in output quality.

It was a shift in who is doing the analysis.

With 5.3:

  • I decomposed the system
  • Codex helped execute

With 5.4:

  • Codex proposes the decomposition
  • I review, validate, and guide

That’s a fundamentally different workflow.


Where this is going

This shift feels important.

If tools can reliably propose architectural changes—not just implement them—then refactoring stops being something we postpone, and starts becoming something we can do continuously.

Not perfectly. Not blindly. But fast enough to matter.

And that changes how we think about maintaining systems over time.

Further reading