Back Arrow
From the blog

This Made Sense at the Time: Why Yesterday's “Bad” Decisions Deserve a Second Look

It lurks in every project older than a year: the code that defies logic. The instinct is to judge. But what if that instinct is holding your team back? At Umbraco Codegarden, I presented a simple yet powerful reframe: instead of asking "Who did this?", ask "What did they know back then?" The insight you gain might just save your next project.

Anna Bastron

Solution Architect

Every experienced developer has encountered it: a piece of code that looks completely irrational. A mysterious workaround. A feature nobody uses anymore. A subsystem everyone is afraid to touch.

The first instinct is usually simple: "Who thought this was a good idea?"

During my Umbraco Codegarden conference talk "This Made Sense at the Time", I've challenged that instinct. Instead of asking who made the wrong decision, I suggested asking a far more useful question:

What did they know when they made it?

The answer, in my opinion, often changes everything.

Because every legacy system tells a story. Imagine travelling back to the exact moment an architectural decision was made - not to change history, but to understand it.

Because software decisions rarely happen in perfect conditions. They happen under deadlines. During incidents. With incomplete information. Inside frameworks that have limitations. And under business pressure that future developers never get to see. When that context disappears, the decision itself often starts looking irrational.

To begin with, let me introduce you to Anna from the past. That's me, eight years and one baby ago. Young. Full of energy. Convinced that good architecture could save any project. Always up for a technical challenge - the harder, the better.

I'm the one who lives with her decisions now. And I've got two stories about that.

Story #1: The Critical Feature That Was Never Used

This was my first project as a solution architect. A global pet food brand. Fifty-something regional teams. Thirty-five languages.

You can already feel where this is going.

The client insisted on one feature. On their old platform, they'd had a legal incident. The kind that ends with lawyers in the room. The cause was oddly specific: in several countries, you can't show a photo of a dog if its tail or ears aren't fully visible. There are laws against cosmetic surgery on animals. A photo that broke this rule had slipped through to one of those markets.

Now they were building a new platform. The fear came with them. The client insisted on one seemingly simple feature: a switch that could instantly remove an entire dog breed from every part of the website. Not just one page. Every language. Every search result. Every taxonomy. Every related article. Every product filter. And without breaking anything else.

Technically, this wasn't something the platform supported. Building it required significant custom development and introduced long-term maintenance costs.

Past-Anna did try to push back. This is going to be painful to build. Painful to translate. Painful to index. Painful to maintain.

The room heard her out. They agreed with every point. And they decided to build it anyway. Not because they missed the cost. Because the scare was fresh - and the switch was their version of safe.

So we built it. Shipped it to every market. I maintained it for five years.

What do you think happened in those five years? Nothing. The switch was never used. Not once. Not for any breed.

Well, not quite nothing. It had to be maintained. Regression tested. Every audit, every onboarding, someone had to pull up the documentation and explain what the switch was, and why it was there.

The client team had changed. The people from the original incident had moved on. But the switch was still there. And past-Anna was still protecting it because, well. It was critical.

Story #2: The Band-Aid That Held Everything Together

A completely different project. A multilingual B2B and B2C ecommerce platform. We inherited it. A different company had built it on a platform that was new to them, and they'd struggled the whole way. It shipped in a panic. By the time it landed on our desks, that team was gone. Our job was to stabilise it.

While working on it, past-Anna found something that immediately made her stop and think: Why would anyone do this?

A piece of middleware was quietly removing the standard language header. And a custom helper was rebuilding the same information from the URL instead.

It looked like a crazy workaround. So we did the obvious thing. Removed the middleware. Deleted the helper. Used the standard language header, like everyone else does.

The code got cleaner. The bug we were chasing got fixed. We tested it. In every lower environment. And then deployed.

What do you think happened? Half the site's languages stopped working.

And we rolled back.

Same code that had passed every test. Same code that had worked perfectly in staging. In production was broken.

So past-Anna started digging through the git history. And here's what she found.

There was a real bug in the framework. It couldn't handle some of the data this project needed to pass through that standard header. Under deadline pressure, the previous team had put a band-aid in place - strip the header, rebuild the data their own way. It wasn't a crazy hack. It was the only way to keep the site up.

Over time, the rest of the application had evolved around that decision. Removing the workaround wasn't a refactoring exercise anymore. It required redesigning part of the platform. The original developers hadn't written bad code. They had solved the problem they actually had.

So why had our "fully tested" fix worked in staging but not in production? The hosting was set up a little differently in each environment. The test environment had been hiding the bug from us the whole time. Production was the first place we actually saw what the band-aid was for.

And the team who built it was gone. Anna couldn't ask why. She could only read what they'd left behind, follow their steps and try to imagine the week they'd had when they wrote it.

The real problem was that nobody had documented why they had done it.

Two Decisions. One Question.

Two decisions. One is a critical feature nobody ever used. The other is a hack the whole system quietly depends on. Very different shapes but they have one thing in common.

They both made sense at the time.

But both outlived their context and became difficult to get rid of.

So the question isn't who messed up. The question is - what do we do when we find one?

The Time-Travel Exercise

Here's the tool.

Imagine a DeLorean. Jump in. Hit eighty-eight miles per hour and travel back to the day the decision was made and asking:

  • What technology existed then?
  • What business requirements mattered?
  • What constraints shaped the solution?
  • What information was unavailable at the time?

Only after reconstructing that context should teams compare it with today's reality.

Sometimes nothing important has changed. Sometimes everything has.

The goal isn't nostalgia. Nor is it defending old architecture. The goal is understanding whether the original assumptions are still true.

Be that person for a minute. Not the version of them you imagine - the real one, with the real deadline, and the information they actually had.

Then compare it to everything you know now. Maybe the requirements have changed. Maybe technology has moved on. Maybe a constraint has quietly gone away.

Or maybe not.

Why This Exercise Helps

It's compassionate. Blame doesn't fix anything. And there's almost always a reason behind a decision past-you made the best call they could with what they had. There's nothing to regret.

It restores the context, so you can compare it to today. Imagine a visual diff tool but for context. Then-and-now, side by side.

But those two columns don't fill themselves. To see the "then", you have to go and get it.

Talk to the team. Read the documentation. Look through the commit history. Get close enough to past-you that you can almost feel what they were feeling.

And then ask the only question that matters:

Does this still make sense?

Back to Story #1: The Critical Feature

So let's actually run the exercise for Story #1.

What was true then? A real legal accident had just happened - content published by mistake on the old platform.

The framework couldn't remove a topic cleanly - a custom switch was the only way to do it. The switch took real effort to build and maintain, and it came with performance tradeoffs.

We built it because the scare was fresh and the switch was the client's version of safe.

Was past-Anna wrong? No. This made sense at the time.

Now let's compare the context.

One thing has not changed. The framework still can't do this natively so the switch is still the only technical way to pull it off. And it still costs what it always costs: effort to maintain, and a drag on the background jobs. So if we were judging by the technology alone, we'd keep it. And keep paying for it.

But look at the risk instead.

In five years on the new platform, there hasn't been a single accident. And not by luck. The new platform gave the client real tools to check what they publish before it goes live. The original accident was a publish that slipped through by mistake. That failure mode is now caught at the source.

So we're paying to maintain a feature, and slowing the system down, to guard against a problem the platform now prevents on its own. And whatever small risk is left? It doesn't need a custom feature on every breed page. It needs a process. A manual or half-automated takedown for the rare case would cover it.

The call: time to revisit. Not because the feature is old. And not because the tech caught up - it didn't. Because the risk changed shape.

We protected it out of habit. Now we can change it out of understanding.

Back to Story #2: The Band-Aid

Now let's run it again for Story #2.

What was true then? A real bug in the framework and no fix coming.

Deadline pressure - release in days, not weeks.

A workaround that looked lightweight, and kept the site alive.

Was that decision wrong? No. This made sense at the time too.

Now let's compare the context.

Much of it is still true. The bug is still there. The system has grown around the hack. Removing it now is a redesign, not a cleanup.

So the call this time: leave it alone for now. But now we understand it. And we can plan the proper redesign on our own terms, instead of being caught off guard by it in production again.

Now the reason Story #2 hurt so much, wasn't the bug. It was that nobody had written down the why. We had to rediscover it the hard way in production.

So if there's one practical thing to take from today, it's this:

When you make a decision under pressure, document the why, not just the what. And if you can, write down what would have to change for this to stop making sense. That's the one note future-you will actually come back and read.

And still even without that note the site stayed up. That mattered.

So knowing the full context, "thank you, past developer" stops being something we say through gritted teeth.

Conclusion

Two Stories. One Tool. Two Completely Different Answers.

Next time you look at something in a project and think "why on earth would anyone do this?" - pause.

Take the trip. Go visit past-them. Instead of assuming past developers made poor choices, assume they were solving yesterday's problems with yesterday's tools.

Sometimes you'll discover it's time for a redesign. Sometimes you'll discover the old solution is still exactly the right one.

And whatever you decide - leave a note for the next traveller. You know the one. The why, not just the what.

Either way, you'll probably reach the same conclusion I did:

It made sense at the time.

It's easy to start working with us. Just fill the brief or call us.

Find out more
White Arrow
From the blog
Related articles

What a 3,000-Year-Old Book Knows About Your Career in AI

Vladislav Bodin

The tech industry is shifting drastically, fueling both opportunity and anxiety, but the real first step is to conquer fear and embrace change not just learn new skills. Clear thinking comes before any career move.

AI

Starting as a Professional Frontend Developer

Yakov Shevcov

In this article, I want to share not just impressions, but real experience of "surviving" in a commercial project. This is an honest story of what to be prepared for if you're looking for your first job.

Frontend
.NET

Speeding Up Layout from Figma with MCP and Cursor

Liya Vasilkova

In this article, I'll show you how to leverage the full power of AI assistants in the design implementation process, using the duo of Cursor IDE and an MCP Server as an example.

Frontend

Setting Up a Frontend Build for HTML Email Templating with MJML

Dmitry Berdnikov

In this article, we'll break down two key stages: first, we'll create a repository for email templating, and then we'll configure local test sending via SMTP.

Frontend

gRPC for Testers: Quick Start After REST

Vasil Khamidullin

This article will help you understand gRPC basics, how it differs from REST, the structure of .proto files, and most importantly- how to test gRPC services using Postman.

QA

Understanding CORS: A Practical Guide

Bair Ochirov

In this article, I will briefly answer questions about why the CORS policy was created, how it works, why a simple action like "setting a header on the backend" might not be enough, and what secure patterns to choose for the frontend.

cors
sop

How I Started Writing Unit Tests for Vue Components - Part 2

Dmitry Simonov

So, it's been a year since the last article, and a lot has changed. In this one, we're going to talk about integrating with Mock Service Worker (MSW).

vuejs
Vue

Performance Issues in Web Services: A Practical Guide to Identification and Resolution

Dmitry Bastron

Performance is not a feature to add later, but a core requirement as vital as security. This guide provides a structured approach to building performance into your web services from the start, ensuring they are fast and scalable by design.

Development
WebDev

Setting SMART Goals for Digital Product Success

Andrey Stepanov

This quick guide helps you define clear objectives and track progress effectively—ensuring every milestone counts.

Development

Building Teams for Digital Products: Essential Roles, Methods, and Real-World Advice

Andrey Stepanov

A digital product isn’t just about features or design—it’s about teamwork. In this article, we break down the essential roles in digital product development.

Development

Goals in Digital Development: How to Launch a Digital Product Without Failure

Andrey Stepanov

Essential tips for creating a development team that works toward product goals, not just tasks.

Development

How to Become a Kentico MVP

Dmitry Bastron

Hi, my name is Dmitry Bastron, and I am the Head of Development at ByteMinds. Today, I’d like to share how I achieved Kentico MVP status, why I chose this CMS, and what it takes to follow the same path and earn the coveted MVP badge.

Kentico

How can a team lead figure out a new project when nothing is clear?

Maria Serebrovskaya

Hello! My name is Maria, and I am a team lead and backend developer at ByteMinds. In this article, I will share my experience: I’ll explain how to understand a complex project, establish processes, and make it feel like "your own".

Development

How I Started Writing Unit Tests for Vue Components

Dmitry Simonov

In this article, we’ll take a look at how you can start testing Vue components.

Vue
vuejs

Inspecting raw database data in Xperience by Kentico

Dmitry Bastron

This article is a cheat sheet to inspect what's going on with the imported data by Xperience by Kentico Migration Toolkit, resolve some CI/CD issues, and on many other occasions!

Kentico

Learnings from using Sitecore ADM

Anna Bastron

Let's try to understand how the ADM module works, its limitations, and tactics for optimising its performance.

Sitecore

Your last migration to Xperience by Kentico

Dmitry Bastron

The more mature Xperience by Kentico products become, the more often I hear "How can we migrate there?”

Kentico

5 Key Software Architecture Principles for Starting Your Next Project

Andrey Stepanov

In this article, we will touch on where to start designing the architecture and how to make sure that you don’t have to redo it during the process.

Architecture
Software development

Assessing Algorithm Complexity in C#: Memory and Time Examples

Anton Vorotyncev

Today, we will talk about assessing algorithm complexity and clearly demonstrate how this complexity affects the performance of the code.

.NET

Top 8 B2B Client Service Trends to Watch in 2024

Tatiana Golovacheva

The development market today feels like a race - each lap is quicker, and one wrong move can cost you. In this race, excellent client service can either add extra points or lead to a loss due to high competition.

Customer Service
Client Service

8 Non-Obvious Vulnerabilities in E-Commerce Projects Built with NextJS

Dmitry Bastron

Ensuring security during development is crucial, especially as online and e-commerce services become more complex. To mitigate risks, we train developers in web security basics and regularly perform third-party penetration testing before launch.

Next.js
Development

How personalisation works in Sitecore XM Cloud

Anna Bastron

In my previous article, I shared a comprehensive troubleshooting guide for Sitecore XM Cloud tracking and personalisation. This article visualises what happens behind the scenes when you enable personalisation and tracking in your Sitecore XM Cloud applications.

Sitecore

Server and client components in Next.js: when, how, and why?

Sergei Pestov

All the text and examples in this article refer to Next.js 13.4 and newer versions, in which React Server Components have gained stable status and become the recommended approach for developing applications using Next.js.

Next.js

How to properly measure code speed in .NET

Anton Vorotyncev

Imagine you have a solution to a problem or a task, and now you need to evaluate the optimality of this solution from a performance perspective.

.NET

Formalizing API Workflow in .NET Microservices

Artyom Chernenko

Let's talk about how to organize the interaction of microservices in a large, long-lived product, both synchronously and asynchronously.

.NET

Hidden Aspects of TypeScript and How to Resolve Them

Dmitry Berdnikov

We suggest using a special editor to immediately check each example while reading the article. This editor is convenient because you can switch the TypeScript version in it.

TypeScript

Troubleshooting tracking and personalisation in Sitecore XM Cloud

Anna Gevel

One of the first things I tested in Sitecore XM Cloud was embedded tracking and personalisation capabilities. It has been really interesting to see what is available out-of-the-box, how much flexibility XM Cloud offers to marketing teams, and what is required from developers to set it up.

Sitecore

Mastering advanced tracking with Kentico Xperience

Dmitry Bastron

We will take you on a journey through a real-life scenario of implementing advanced tracking and analytics using Kentico Xperience 13 DXP.

Kentico
Devtools

Why is Kentico of such significance to us?

Anastasia Medvedeva

Kentico stands as one of our principal development tools. We believe it would be fitting to address why we opt to work with Kentico and why we allocate substantial time to cultivating our experts in this DXP.

Kentico

Where to start learning Sitecore - An interview with Sitecore MVP Anna Gevel

Anna Gevel

As a software development company, we at Byteminds truly believe that learning and sharing knowledge is one of the best ways of growing technical expertise.

Sitecore

Sitecore replatforming and upgrades

Anastasia Medvedeva

Our expertise spans full-scale builds and support to upgrades and replatforming.

Sitecore

How we improved page load speed for a Next.js e-commerce website by 50%

Sergei Pestov

How to stop the decline of the performance indicators of your e-commerce website and perform optimise page load performance.

Next.js

Sitecore integration with Azure Active Directory B2C

Dmitry Bastron

We would like to share our experience of integrating Sitecore 9.3 with Azure AD B2C (Azure Active Directory Business to Consumer) user management system.

Sitecore
Azure

Dynamic URL routing with Kontent.ai

We'll consider the top-to-bottom approach for modeling content relationships, as it is more user-friendly for content editors working in the Kontent.ai admin interface.

Kontent Ai

Headless CMS. Identifying Ideal Use Cases and Speeding Up Time-to-Market

Andrey Stepanov

All you need to know about Headless CMS. We also share knowledge about the benefits of Headless CMS, its pros and cons.

Headless CMS

Enterprise projects: what does a developer need to know?

Fedor Kiselev

Let's talk about what enterprise development is, what nuances enterprise projects may have, and which skills you need to acquire to successfully work within the .NET stack.

Development

Fixed Price, Time & Materials, and Retainer: How to Choose the Right Agreement for Your Project with Us

Andrey Stepanov

We will explain how these agreements differ from one another and what projects they are suitable for.

Customer success

Sitecore Personalize: tips & tricks for decision models and programmable nodes

Anna Gevel

We've collected various findings around decision models and programmable nodes working with Sitecore Personalize.

Sitecore

Umbraco replatforming and upgrades

Anastasia Medvedeva

Our team boasts several developers experienced in working with Umbraco, specialising in development, upgrading, and replatforming from other CMSs to Umbraco.

Umbraco

Kentico replatforming and upgrades

Anastasia Medvedeva

Since 2015, we've been harnessing Kentico's capabilities well beyond its core CMS functions.

Kentico

Interesting features of devtools for QA

Egor Yaroslavcev

Chrome DevTools serves as a developer console, offering an array of in-browser tools for constructing and debugging websites and applications.

Devtools
QA

Activity logging with Xperience by Kentico

Dmitry Bastron

We'll dive into practical implementation in your Xperience by Kentico project. We'll guide you through setting up a custom activity type and show you how to log visitor activities effectively.

Kentico
This website uses cookies. View Privacy Policy.