Architectural decision records and the quest for consistency

By Dane Hillard

ITHAKA Tech Staff
ITHAKA Tech
6 min readJul 6, 2023

--

While offices like ITHAKA’s Ann Arbor offices pictured here sit partially empty during hybrid and remote work, ADRs have become even more important to help teams track decision making and collaborate.

Today you break ground on a brand new product. You’ve just left the kickoff framing the problems to solve and your mind is buzzing with possibility. Because no one has built anything yet, every piece of the puzzle is a fresh opportunity to make the perfect decision. You can make decisions quickly because you don’t yet have any users, contracts, or cares in the world. You crack your knuckles and hunker down to discuss with the rest of the engineers.

A few weeks go by. The team has delivered a few valuable increments of the product to positive user feedback, and they have plenty of runway left with insight from discovery. They’ve been knocking things out of the park but something’s starting to feel … off. You can’t quite put your finger on it, but each decision the team makes now feels like a challenge.

Discussions around new decisions now include the details of past decisions, and the nuances have started to muddy the waters. You find yourselves saying, “Oh, we would need so-and-so here to answer that” more and more often. You start relitigating things you thought were clearly defined and aligned. It gets harder and harder to keep it all straight.

Finally, things come crashing down. You decided to go one direction, but because you had forgotten about a previous pivotal decision and the constraints that led to it, the team is now in triage mode trying to figure out how to recover from the issues. While they scramble to mitigate user impact, you pore over old documents and artifacts and sticky notes in hopes of rationalizing the state of affairs.

As our systems grow in capability and complexity, they quickly become more than any one person can keep in their head. What’s more, the shape of the system doesn’t typically communicate the circumstances that led to that shape. Even the most detailed system diagrams don’t necessarily explain how they came to be:

  • Which of these pieces were intentional? Which were incidental?
  • Which of these pieces are constrained by the needs of users vs. the needs of the business?
  • How much of the system was guided by specific technology choices and how much by broader design patterns?

None of this information is directly stored in the system itself, and it can slip away if we don’t take care.

Using architectural decision records

Architectural decision records (ADRs) help shore up the history of decisions about a system. ADRs record important structural design decisions along with the context when the decision was made so that anyone can explore the pedigree of the system.

By recording not just the drivers but also the constraints, reasoning, and accepted consequences behind a decision, we enable anyone exploring the ADRs to learn a lot about the system’s current shape. Instead of knowing simply how the system behaves, people can learn why the system behaves.

Sample ADR: Broad strategy decisions

The following is a real ADR we wrote at ITHAKA around micro frontend architecture. This decision was broad enough in scope to drive an entirely new area of investment for the UI Engineering department:

# Use micro frontend architecture

## Context

Shifting industry practices are driving the desire for fungible commodity
features, provided to both external end users and internal users alike.
To remain competitive, teams need to deliver composable units of value
that can be integrated and reintegrated into new product experiences.
These units of value should be small enough such that they can be rebuilt
or thrown away without significant loss of investment.

Especially at the frontend, where services have historically culminated
into a monolithic application that serves the user experience, teams can
gain independence and agility to move faster while also having strategic
discussions about how to leverage each others' work in building the product.

## Decision

Use micro frontend architecture to decompose pages into independently
developed, delivered, and tested experiences with tight ownership by
specific product teams.

## Consequences

Micro frontend architecture flips the paradigm we've used for software
ownership on its head. Whereas teams have historically owned and tested
full pages, we now need to think about ownership in terms of experiences
that may span a user's entire session across several pages. In practice
this involves a higher emphasis on contracts.

With tightly focused experiences, we will be able to iterate more quickly
on validating and delivering changes to those experiences. We will need to
invest further in experimentation tooling. In practice, we can deploy two
entirely divergent variants of a micro frontend and choose which of them to
serve, because there's significantly less overhead to doing so.

Because parts of pages are independent applications, tooling for developing,
testing, and deploying those applications may need to change. In practice,
we need to determine integration points, error boundaries, and fallback
behavior. We will need to consider the impacts on core web vitals.

Sample ADR: API design

ADRs need not be as lofty as the previous example, though — they can describe something as small as a function signature. Here’s another real example from JSTOR’s Pharos design system that sits somewhere in between, describing a process for backward compatibility:

# Evolve design tokens in backward compatible manner

## Context

When teams are using micro frontends with module sharing, the precise
version of a component is not guaranteed.

This means removing a token that seems unused by the current component code
base is still a breaking change. Distributed teams experience this when
trying to use a component that expects newly-available tokens without having
updated the version of tokens available on the host application first.

An improved protocol would ensure that using new tokens and removing old
tokens has failsafes in place.

## Decision

Use an "add-only" approach for design tokens with a fallback mechanism for
backward compatibility.

## Consequences

- Removing tokens must be treated as a breaking change.
- Usage of newly-added tokens must provide fallbacks. As an example,
`var(--new-token, var(--old-token))`.
- Removing fallbacks must be treated as a breaking change.
- Tokens we want to remove should be marked as deprecated so consumers can
audit their usage footprint.

ADRs as an accountability tool

ADRs also serve as an accountability tool. When the team begins to question things, the ADRs can ground them in their previous agreements. This can save a good deal of time in decision-making, and encourage the team to focus discussions on new directions. Mind you, ADRs aren’t meant to set anything in stone. They can and should be revised with new entries when constraints or drivers change.

Ultimately, ADRs act as documentation of the system’s evolution over time. They give a sense of both the position and movement of the system. If we are to engineer effectively, we need solid situational awareness of our systems so we can bend them to our needs. ADRs are a fantastic way to bring new team members up to speed to become effective more quickly as they start to contribute.

We use the helpful adr-tools command-line interface (CLI) for managing our ADRs. The CLI makes it easy to create, connect, collate, and visualize the records so people can get the most out of them. This project follows the format for ADRs suggested by Michael Nygard in his introductory article on documenting architectural decisions.

Today, ITHAKA’s engineering team has more than 50 ADRs across 12 projects and growing. We aren’t just using them at the project level, either. As with the micro frontend example, we use ADRs to describe practices and decisions we want to follow generally as a team and as a department. We’ve been able to point to these ADRs when someone asks why something is the way it is, and it’s saved us on more than one occasion from taking a path where another team had already discovered pitfalls.

You might be interested in creating decision records for your teams and projects but worry about the initial administrative burden of logging all your decisions to date. It’s never too late to get started, though, and the best time to record decisions is while you still remember what they were. You’ll be thankful to have recorded some decisions even if you don’t capture every decision you’ve ever made. As with most software development and documentation, the intent is for you to iterate and refine over time rather than to be perfect right now. Starting an ADR can also prompt you to take stock of things you might have been taking for granted and review your projects with fresh eyes. Maybe you’ll find a new solution lurking.

Interested in exploring careers and Ann Arbor jobs or New York jobs with ITHAKA? Check out our ITHAKA jobs page to learn more and speak with recruiting.

--

--

ITHAKA Tech Staff
ITHAKA Tech

Insights from the ITHAKA engineering team and beyond.