The North Star Exercise

How do you improve bad software architecture? Introducing low risk, incremental changes is pretty straight forward but improving architecture often involves bold leaps such as complete rewrites. Where do you start?

Here's a strategy I've been using: Imagine the future you want without worrying about how to get there. I'm calling this a North Star Exercise.

Forget about how

Making big changes to software is hard and you might think it can't be done. Regardless of whether that's true or not, the exercise works best when you don't worry about the how part.

As a developer, dealing with the pains of bad architecture can feel overwhelming. This is the voice I typically hear in the back of my head: how will we ever find time to fix this?

Is building a new product from scratch your only chance to build the right architecture? Once it ships and has real users, there aren't many incentives to change the architecture. In fact, doing so could slow down the delivery of features.

I'm not talking about obvious catastrophes like performance. Those are show stoppers. Consider long term quality improvements such as introducing automated tests when there weren't any before. Your team will naturally move slower, spending time on tests. It's hard to make a business case for slowing down.

There are good reasons to slow down but, sadly, a business can still operate on bad architecture. Skilled developers can always "find a way." Accepting bad architecture as the status quo is a classic dilemma.

What's even worse is sometimes you only know the architecture is bad after trying to build real products with it. Thus, spending a lot of effort up front on the architecture could be a waste of time (now you're in a catch-22).

It's not hopeless

For the North Star Exercise, you can ignore the how and ignore the business pressure of constantly shipping.

Isn't that nice?! I find this exercise very cathartic, especially when burdened by legacy code.

Imagine the future

You are now free to imagine a better world. Consider a product your team works on and pick any programming language, any framework, any technique, or any tool.

The North Star Exercise is completely aspirational. You will also have the benefit of hindsight and all of those architectural mistakes that haunt you every day.

Declare the future

Now it's time to write a document. I like to declare the future as if it already happened. I include at least two bullet points with each declaration, benefits and fun factors, but you can add anything.

Here's an example from my recent North Star Exercise:

All products are built with a unified design system

The benefits are more like solutions to problems. The fun factors add to the joy of software development. This declaration is pretty high level but it could be low level, too, such as all web apps are written in React. It could also be more abstract like all code intent should be verifiable through static analysis.

Documenting the benefits is key because developers are always tempted by shiny frameworks and new languages. It's important to make sure there are real benefits to changing the architecture.

For context on the design system aspiration, I was dealing with a setup of disparate UIs across languages and frameworks (native iOS, native Android, React, Angular 1, etc). Moving them all to a unified design system would be a big change! Most apps would need to be rewritten from scratch.

Again, I was free to ignore how. For the exercise, I simply declared the future I wanted and why.

OK, really, how do you get there?

The North Star Exercise can be a guide for future planning. Using the example above, I could propose to rewrite all mobile apps in React Native so they could share the same design system. I could research ways to share design system logic across both React Native and React for web. I could propose porting the Angular 1 app to React or consider a framework-agnostic design system, and so on.

The dream of a unified design system was massive. I used the North Star Exercise like a drone, flying over the entire product portfolio, considering everything in harmony.

As with any architectural change, it helps to start with proposals to vet ideas and collaborate on the best solution. Architectural decision records are a lightweight way to do it but simple RFCs (requests for comments) would work, too.

Ideally, I'd try to propose low risk, incremental changes toward a distant goal along with a plan to keep the business operational. For bigger chunks of work, I'd plan out a research phase, a prototyping phase, create a backlog of tasks, propose some metrics for knowing when to pull back, etc.

The Chrysalizer Pattern, Ship of Theseus, Big Bang, or any other rewrite pattern will offer concrete ways to actually usher in big changes.

What if you never get there?

That's OK. You might get close. You might simply set up future products for success. You will give everyone a better understanding of what it feels like to deal with bad architecture. If nothing else, it should spark the right discussions.

Naturally evolving architecture

The burden of legacy code takes many different forms and some architecture is easier to change than others. Patterns such as microservices (even for the frontend) make it easier to evolve software architecture over time. There are trade-offs but mostly it acknowledges that architecture needs to constantly evolve.

If you're already dealing with those then you may not be so heavily burdened by the act of changing architecture. Congrats!

Also, you may have time allotted for fixing "tech debt" as part of your product delivery process. This is usually great but there are pitfalls since not all tech debt is bad and not all architecture changes are worth it. If nothing else, it helps to track a backlog of tech debt and constantly re-prioritize it.


I don't know where the North Star Exercise originated but Michael Ten-Pow first told me about it. Thanks, Michael.

I've also heard reference to a north star in tech meaning the direction an org is heading in. That's a separate concept more about declaring a mission or product vision.