The Value of Stare Decisis in Evolving a Mature Tech Stack

The United States legal system, like many other English-derived legal systems, is a Common Law system where the laws passed by the legislature are not intended to be exhaustive. Instead, judges must decide specific adversarial cases based on their interpretation of those laws and produce written decisions. Lawyers can look at previous decisions to make an educated guess based on the facts they are presented with in a specific case to determine if it is worth pursuing the matter further.

An obvious flaw of this system is the potential for the whims or biases of individual judges to lead to wildly different outcomes. Without the ability to rely on decisions in the future, it is difficult or impossible to know who might prevail in a dispute, resulting in wasteful re-litigation and inconsistencies that need to be resolved by higher courts. To combat this, Common Law relies on the principle of Stare Decisis, literally “let the decision stand”. In short, similar cases should be decided with similar outcomes by treating earlier decisions as partially or completely binding on subsequent decisions. Courts must then look at each dispute presented and determine if the facts are similar enough to a prior binding decision that the outcome is effectively predetermined, or conversely, novel enough to warrant a newly-reasoned decision.

There is a narrow path that avoids adhering to the principle too closely or too loosely. If the original decision was wrong, blindly sticking with it for an extended period of time can result a long sequence of bad outcomes (see: Plessy v. Ferguson) It can also be the case that a decision made sense at the time, but circumstances have changed in a way that makes that previous decision somewhat or entirely incorrect. On the other hand, adhering too loosely results in uncertainty and waste as more complexity and nuance is added to decision making process. It is likely to take much longer to reach a decision in each case, with more cases needing to be considered more deeply.

As software architects, we find ourselves in an analogous situation. In place of new cases being considered for adjudication, engineers evaluate each new feature and new requirement to determine if an existing pattern can be used to satisfy it (Stare Decisis), or if it presents a fundamentally new capability that requires a newly-designed solution (New Precedent). Like in the law, there is danger in leaning too much to one side or the other. If we lean too far on the side of relying on existing patterns, we can find ourselves with an “everything is a nail” situation, pressing existing ways of working into inapposite service with predictably poor outcomes. If we lean too far the other way, the codebase becomes riddled with a million logic paths and overall fragility since the abstractions and generalizations that might have been used to handle future cases and change more broadly are weak or absent.

The legal world has been tangling with this challenge for centuries and it is instructive to look at their approaches. In 1765, William Blackstone wrote that in the English tradition there was a strong presumption that, to promote stability in the law, judges would abide by former precedents, unless such precedents were “flatly absurd or unjust” (William Blackstone Commentaries on the Laws of England 69–70). Similarly, Justice John Marshall in establishing the early Supreme Court combined a strong preference for adhering to precedent with a “limited notion of error correction“. This seems like generally good advice in the engineering space as well: try to use and extend the capabilities to cover new situations as much as possible.

But what about those “flatly absurd or unjust” prior decisions, or the “limited notion of error correction” Justice Marshall describes that form the exceptions to the rule? The law certainly corrects itself (see: Brown v. Board of Education with regard to Plessy v. Ferguson) and the justices in those decisions go to great lengths to explain why they have chosen to diverge from previous precedent. This might include:

  • An explanation of the unjust or absurd outcomes that have arisen from the decision, and how the new precedent avoids or resolves though so as to ground it in a better moral or logistical foundation.
  • A description of the changed real-world circumstances that have invalidated or otherwise called into question the current precedent.
  • Careful compartmentalization of the new precedent so that only a specific narrow new set of cases would apply, while leaving other decisions in place.

These guidelines work well for engineering decisions as well, and can help add legitimacy to technical decision making:

  • An explanation of unjust or absurd outcomes – “We have previously standardized on Framework X for building APIs, but it requires us to maintain nearly 200 lines of boilerplate code in every project. Framework Y does not have this requirement which is why we would like to adopt it” or “we are entirely dependent on third-party service A, but the new feature we are requesting will require several months of their work to support. We can replace A with a custom-built B that will better suit our needs going forward.”
  • A description of changed real-world circumstances – “A new cloud-based service is superior to our current offering (on features/cost/resiliency)” or “Framework X has reached the end of its life and is no longer supported, Framework Y is the natural successor”.
  • Careful compartmentalization of the new precedent – “All of our existing services use Java, but we would like to innovate on a new high-performance service and use Rust which might become a second supported language under the right circumstances”

Engineering decisions have some additional considerations when looking at when to diverge from existing precedent:

  • Impact/work created – The US legal system does not have any requirement to consider what would have to be changed to comply with a changed precedent, but that can have a major impact on engineering projects. Considering and surfacing the resulting work to change (as well as the work avoided by doing the change) is a critical input to the decision-making process. A slightly inefficient pattern that has been adopted widely can be far more costly to change than the resulting benefit gained, but a large improvement that impacts only a small part of the codebase should be easily prioritized.
  • Cost of Fragmentation – The US legal system does not require any sort of plan for dealing with the fact that there may now be a legacy legal framework which led to certain outcomes, and a new legal framework that would lead to different ones. In some cases, addressing the management of the old and new frameworks (or creating a plan to move all outcomes to the match the new framework) is at least considered or even mandated, but that is generally left up to the affected parties to resolve. In engineering, there is a real cost to maintaining multiple patterns for the same capability, which, if ignored leads down the path to the Lava Layer anti-pattern. It may be that although there is general agreement on the changing of a precedent, there is neither the will nor the funding to avoid fragmentation which would be worse than simply leaving the current precedent in place.
  • Developer Morale – The US legal system does not concern itself with the effects of rapid change, and there are many instances historically where wild swings in precedent due to new case law or appeals cause a fair amount of chaos in legal decision-making, with a real impact on litigants who lose faith in the process due to its unpredictability. Similarly, developers who find themselves constantly having to change to adopt new precedents in pursuit of higher engineering standards or more general API contracts can burnout on the constant shifts which leave them in the position of either constantly making non-productive changes to simply stay aligned, or leaving behind tons of legacy layers that pile up as hardened tech debt.

Ultimately though, final legal authority rests in the US Supreme Court to either uphold the new precedent or decide that the previous standard should remain, and the legitimacy of those decisions is in many ways based on public support to actually enforce the consequences of those decisions. Consensus building is an under-appreciated skill in managing and evolving a mature technology stack, but crucial in retaining legitimacy as new precedents are evaluated and eventually adopted. The engineering team must be bought in to the change in precedent, or they will simply ignore it and continue to do what has been done in the past, regardless of its merit.

As an exercise for the reader, consider:

  • What precedents exist today that you would like to change, and what is preventing that change from happening?
  • What precedents have you attempted to change, and either succeeded or failed? Have you considered why in each case?
  • Where have you adopted a new precedent and then regretted it?

Leave a comment