Ship Every Day in October: A CMS Migration [Part 3]

ChatGPT'd "Draw me a LinkedIn header for Ship Everyday in October"

At the beginning of October, I set myself a challenge: Ship something every day of the month.

Part 3 of 3 in my CMS Migration Series:

  1. Feeding the AI Vampire: A CMS Migration [Part 1]
  2. Is the Vampire Juice worth the squeeze: A CMS Migration [Part 2]

I’d been feeling the need to shake things up. I was increasingly enjoying being hands-on with AI and building software, but I was also struggling to balance being a maker with being a manager. Leading an engineering team of nine, owning the technology, and dealing with everything else that comes with the job doesn’t leave much uninterrupted time for writing code.

I needed to change my habits, rethink how I worked, and experiment with different approaches. Rather than promising myself I’d make more time, I decided to create a constraint that would force me to do things differently. Could I ship something useful every day, while still doing my day job?

There was also the not insignificant matter of getting our CMS migration finished. Having written about becoming an AI Vampire, I was already in deep with the project, and the pressure to deliver wasn’t going away.

So, why not make things even more interesting…

A Month of Shipping

I did it. Every day in October.

Not bitter... A missing green Github square. I was hoping for all green!
Not bitter… But I was hoping for all green!

During the working week, that often meant getting up early, occasionally working late and trying to find time around all else going on. At weekends, I’d squeeze in the odd side quest before the kids woke up. Often something smaller, useful to me, or simply something I fancied experimenting with. Fun, even more fun once the migration was complete!

The CMS migration provided plenty to work on. And once finished, I found myself with A LONG list of things I wanted to tidy up, improve or revisit. But the challenge was never about how much code I could produce. I wanted to explore how I could work differently, make better use of AI, and create more options for myself (and the team) without simply adding hours to the day.

I started spending even more time thinking about the shape of a solution. Noodling with Claude or Grok to get the plan ‘right’, exploring options and challenging my assumptions. Opus 5.5 and Grok 4.7 then make implementation joyful. Through multiple commits and working together, gently nudging forward in an addictive and highly productive flow state. Using /code-review to gain further confidence in the approach and ensure we’ve not missed anything. Understanding the problem, planning the approach, and deciding how to break work down are still the highest-leverage activities. Pre-AI as well, it reminds me of “Give me six hours to chop down a tree and I will spend the first four sharpening the axe.”attributed to Abraham Lincoln.

Without this, and even sometimes with, the speed Opus 5.5 and Grok 4.7 develop mean I can also get myself off track much faster. Leading to wasted effort and binned code. This still doesn’t feel comfortable, but at this speed, it is more efficient than investing further time to fix an errant session! The rollback features of sessions, and sometimes deleting a branch, are an effective way to get back on track.

Playing 4D Chess

I started leaning into worktrees and stacked PRs.

Until now, I’d largely been operating with a single branch and only using multiple agents and sessions when involving more than one repo. I’d work on something, get it to a sensible point, raise a PR and wait for review. If I needed to do something else in the meantime, I’d juggle local branches, context and the state of whatever I was working on. Which led to diminishing returns and more time and energy lost to context switching.

Worktrees changed that!

They easily supported multiple agents working independently, sometimes across multiple repositories, without constantly interfering with one another. Stacked PRs then offered more options to manage dependencies, reviewing, and shipping. It felt like playing 4D chess. Strategically deciding what to work on, which changes depended on others, what to get reviewed first, and how best to ship. And, rather wonderfully, I enjoyed it. Worktrees and Stacked PRs provided a layer of optionality and management to reduce the effort and time spent managing multiple sessions and agents.

I’ve also been further experimenting with Cursor, vsCode, Claude Code and Codex, using local and cloud development, CLIs, Apps and extensions. Different tools for different jobs, rather than trying to make one tool do everything. I even found myself working from Cursor on my iPad while staying in a hotel with the family. I’d prepared a small change in advance, removing a person of interest field from a microservice. With GitHub on the iPad giving me more options for reviewing and managing changes away from my Mac.

Not exactly how I imagined I’d be developing software a few years ago.

The big thing for me wasn’t the iPad, or even the ability to have several agents working simultaneously. It was that I was finding new ways to fit development around everything else. I’ve settled, for the moment, on Cursor for worktrees, vsCode with Claude for local branches, and then for /code-review using OpenAi’s Codex App and Claude via the terminal. This gave me flexibility, spread my token spend/subscriptions, and seemed to be the most efficient. I also found it better to limit sessions to a single Jira ticket, branch and repo. That enabled me to manage the PRs, tickets, and flow of work more efficiently. The 1-1 session-ticket-repo mapping helped track and plan the work. The limits of what I could keep in my head where long breached. The 1-1 mapping also made it easier to pick up and put down work, making it easier to respond to the manager side of my role and requests from the team and business.

Finding the friction

Spending so much time hands-on allowed me to experience the same frustrations and friction points as my engineers. As said in other posts, our CI/CD pipeline is glorious! A credit to our DevOps wizard and the work that’s gone into making deployments fast, reliable and largely uneventful.

Getting code into production is, for the most part, a pleasure.

Getting code reviewed, on the other hand…

This is something I’ve been aware of and also mentioned before, and we’ve been wrestling with as a team. AI has accelerated how quickly we can create changes, but it hasn’t magically increased everyone’s capacity to review and understand them (yet).

I found myself with changes ready to go, stuck waiting for reviews. Meanwhile, the team were busy delivering their own sprint commitments, and the last thing I wanted was to land a substantial PR on someone’s desk and make my problem theirs.

There was also the sheer volume of code to understand. Reviewing changes is tiring, particularly when you’re moving between several different pieces of work, each with its own context and dependencies.

Having a separate agent review your work pre-PR, especially when it wasn’t the one that produced it, has been useful. It catches issues earlier, and crucially reduces noise and helps us approach the reviews with more confidence. A key guard rail, with Bugbot also as a backstop on all open PRs.

But it doesn’t remove the need for engineering judgement.

And, it certainly doesn’t remove the cognitive load.

Looping on a flakey test

One of my favourite discoveries came from investigating a flakey Playwright test. I came across an intermittent failure that initially looked like something was going wrong with navigation on our Sell With Us page. Clicking through to the valuation form would sometimes display the correct page, but leave the wrong URL in the address bar. Refreshing or using the Back button could then take you somewhere unexpected. It was rare but happening elsewhere too, including our Work With Us and Articles pages.

Not ideal.

My gut suggested it was an existing issue that additional testing had exposed. I developed a theory: our header search was using a history router, which could schedule a URL update before navigation and write it several hundred milliseconds later. If you navigated to another page while one of those updates was pending, it could overwrite the new URL with the old one. A lovely little race condition. The kind of intermittent behaviour that’s a pain to reproduce and diagnose.

I’ve had sessions with Claude and Grok span several days, going backwards and forwards, refining approaches, reviewing results and prompting them through the next steps. But this was different. This time I left a single Claude Code session looping, unsupervised, for four hours.

Four hours without needing another prompt from me or intervention. It repeatedly ran our Playwright tests in the background, and checked for any regressions. Rather than needing me to keep steering it, the agent was able to keep iterating towards a conclusion of 10 full runs without issue. That’s the longest I’ve had an agent work autonomously, and it genuinely took a load off my mind and helped assure me the fix was good to go.

The eventual fix was relatively small. Remove URL routing from the header search, while preserving the search behaviour where it was actually needed. But the implications were much bigger than the size of the change suggested. I was changing production code that affected header navigation, search behaviour and the relationship with our Product Listing Pages (PLP). Getting it wrong could easily have introduced problems elsewhere on the site. This was absolutely a change that needed a proper human review.

The agent’s regression testing loops gave me the confidence to raise the fix for review, with the extensive testing and investigation behind it. I raised the PR for the team to review, including asking Product to confirm that nothing depended on the old search URLs. All without spending four hours of my time watching test runs and trying to reproduce an intermittent failure.

AI value isn’t always in writing more code. Sometimes it’s having an agent take responsibility for a particularly tedious piece of work, while I concentrate on the decisions that actually need me.

Taking responsibility for shipping

The review bottleneck also led me to make some decisions I’m still reflecting on. At times, I used my position and responsibility to bypass our normal PR review process and release changes into production.

Not because I don’t value reviews. Quite the opposite. I didn’t want to overwhelm an already busy team with substantial changes that I’d created while they were committed to their own sprint work.

But I was also conscious of the risk.

I tested changes extensively before release, used Datadog and our logs to monitor behaviour, and improved some of that observability along the way. I’d generally release during quieter mornings or evenings, leaving plenty of space between changes and watched what happened.

Crucially, I also had confidence in our CI/CD ability to roll back in under three minutes if something went wrong.

I’m pleased to report that the month passed without any bugs or issues resulting from my releases, no lost bids and no downtime. I didn’t need to roll back, either. That doesn’t mean bypassing reviews is a good general solution, or that getting away with something proves it was the right decision…

It does mean I experienced a problem we’re trying to solve as a team, and had an opportunity to experiment with ways of reducing the friction. I’d much rather build a system where we can get small, well-tested changes reviewed and released without creating unnecessary work for one another.

We’re not there yet.

The AI Vampire strikes again

Looking back, October was hugely enjoyable. I delivered the CMS migration, shipped something every day, experimented with new tools and approaches, and learnt first hand about the friction in our engineering processes.

But there was a cost.

At times I was juggling six changes simultaneously, with agents running across worktrees, repositories and cloud environments. Each change needed some combination of planning, direction, review, testing or decisions about what to do next.

The cognitive load was real.

It was genuinely exhausting at times. And because I was enjoying the building so much, it became all-consuming. Which rather brings me back to the AI Vampire. I had found ways to get dramatically more done as a maker, but I hadn’t necessarily found ways to balance that with being a manager.

There’s a limit to how much attention I can give to building software while also leading nine people, supporting the team, dealing with the inevitable interruptions and thinking about where we need to go next.

Being hands-on has helped me understand our technical problems, but perhaps more importantly, it’s helped me experience where our engineering system is creating friction. I wouldn’t have learnt nearly as much about our review bottlenecks, tooling or ways of working if I hadn’t been living with them myself.

Now the challenge is what to do with those lessons.

I want to retain the curiosity, experimentation and enjoyment of building things, while finding a more sustainable balance. That means being more deliberate about what I take on, making better use of delegation, and working with the team to improve the processes that slow us down.

October proved that I could ship something every day.

I’m not sure it proved that I should.

But it certainly succeeded in shaking up my habits and changing how I think about working.

And that, ultimately, was the point.

2 thoughts on “Ship Every Day in October: A CMS Migration [Part 3]”

Leave a Reply