One of the easiest mistakes in engineering is assuming that the person before you should have known better. You open a pull request and see a strange workaround, you look at an old service and wonder why anyone would have split the logic that way, or you find a deployment process with three manual steps and a warning in the README that says do not run this on Fridays. You stare at it for a minute and think, who designed this mess?
Sometimes that reaction is fair. Sometimes the design really is bad, the code really is careless, and the process really is a pile of fear, habit, and avoidance wearing a thin coat of documentation. But a lot of the time, the thing you are looking at is not stupidity. It is context you do not have.
Get past your own ego first
That sounds harsher than I mean it, but it is true. A lot of bad technical judgment starts with the quiet assumption that we know better. We look at the code, the design, the deployment process, or the old decision, and we assume the answer is obvious because it is obvious from where we are standing. That is the trap. Your perspective may be fresh, but that does not make it complete. You may see real problems without understanding why those problems exist, and you can be right about the better design and still be wrong about the path that got the system here.
Getting past your ego does not mean pretending bad work is good. It means admitting that your first reaction is probably under-informed. That is where the better question starts. Not "why did they do something so obviously wrong," but "what context am I missing?" That question has saved me from being confidently wrong more times than I like to admit.
The code did not get better, the context got wider
Every experienced engineer has lived some version of this. Someone reviews your code and asks why you did not use the obvious pattern, and they are not wrong from where they are standing. The pattern is obvious, the code does look awkward, and the abstraction does look strange. Then you explain that the obvious pattern breaks a customer workflow that was promised six months ago, or that the system has an undocumented dependency on a vendor payload, or that the clean solution would have required touching a service nobody owns anymore, or that the last production incident came from exactly the kind of change they are recommending. Suddenly the obvious answer is not so obvious. The code did not get better. The context got wider.
That is the part we forget. Technical decisions do not happen in a vacuum. They happen inside deadlines, incidents, org charts, customer commitments, staffing gaps, vendor limitations, half-finished migrations, and systems nobody fully understands anymore. By the time you see the code, most of that history is gone. You see the decision but not the pressure, you see the workaround but not the incident that created it, you see the coupling but not the customer contract that made it unavoidable at the time, and you see the manual process but not the failed automation attempt that quietly burned the team six months earlier.
Separate judgment from diagnosis
A lot of bad engineering conversations fail right there. Someone walks in with fresh eyes, which is valuable, but they confuse fresh eyes with complete vision. They see the local mess and assume the people closest to it were careless, and the people who built or maintained the system get defensive because they know the history. Then both sides stop learning. The new person thinks the old team lacked discipline, the old team thinks the new person lacks respect, and usually both are missing something.
The healthier move is to separate judgment from diagnosis. You can say this design is creating operational risk and still ask what made this design seem reasonable when it was created. You can say this deployment process needs to be automated and still ask what broke the last time someone tried. You can say this abstraction is too clever and still ask what duplication or pain it was originally trying to remove. That is not softness, that is engineering discipline, because once you understand the context you can fix the actual problem instead of just attacking the symptom.
If a system has a strange workaround because of an undocumented vendor behavior, removing the workaround without understanding the vendor behavior is not cleanup. It is vandalism with good intentions. If a team has a manual release checklist because rollback is unreliable, yelling about automation misses the point, because the better fix may start with rollback discipline, artifact promotion, environment parity, and smaller releases. If a service has unclear ownership because three teams depend on it and none of them fund it, rewriting the service will not solve the ownership problem. Most architecture problems are ownership problems.
Context, not just shoes
Context is not background noise. Context is part of the system. That is why "walk a mile in my context" is more useful to me than "walk a mile in my shoes." The shoe version is about empathy, and empathy matters, but in engineering it can stay too vague. The context version is more operational. It asks what constraints shaped the decision, what tradeoffs were visible at the time, what information was missing, what risks were known, and what pain the team was trying to avoid.
That is a practical habit. Before criticizing a design, walk a mile in the author's context. Ask what they knew and what they did not know. Ask what was on fire, who owned the system, and what deadline was real. Ask what rollback looked like, what customer commitment had already been made, and what political, technical, or operational constraint made the clean answer expensive. You may still decide the design is wrong, and you probably will sometimes, but you will be wrong less often about why.
The why determines the fix
That matters because the why determines the fix. If the problem was lack of skill, the fix might be coaching. If the problem was deadline pressure, the fix might be planning and scope control. If the problem was missing ownership, the fix might be a clearer service boundary. If the problem was fear of production, the fix might be better rollback, safer deploys, and smaller changes. If the problem was incomplete context, the fix might be documentation, decision records, better handoffs, or simply more honest conversations between teams. Different causes produce different repairs.
When we skip context, we reach for generic solutions. We say add tests, refactor it, document it, automate it, or move it to the platform. Those may all be good ideas, and they may also miss the real reason the system is broken.
Production reveals the context people left out
This is one of the reasons I care so much about production systems. Production has a way of revealing the context people left out. The architecture diagram says the service depends on two downstream systems, and production says it depends on six, plus a nightly file, plus a customer-specific configuration nobody remembers. The sprint plan says the feature is done, and production says support does not know how to troubleshoot it. The pull request says the code is clean, and production says rollback was never considered. The deployment pipeline says green, and production says the team does not trust it enough to deploy without Sarah on the call. The system is what happens after the code ships, and that is where missing context becomes expensive.
Prompt engineering without context engineering
This is also why the AI conversation has become so interesting to me. A lot of people talk about prompt engineering as if the magic is mostly in phrasing: better verbs, better structure, better examples, better instructions. That all matters. But prompt engineering without context engineering is just asking a capable system to guess well.
The model has the same basic problem people do. It can only reason from the context it has. If you give it a narrow slice of the world, it will optimize inside that slice, and sometimes it will do that beautifully and sometimes it will produce a clean, confident answer that is completely wrong for the actual situation. That is not because the model is dumb. It is because the world was missing. The same thing happens with engineers. Give an engineer only the code, and they will optimize the code. Give them the incident history, customer promises, deployment constraints, ownership boundaries, and operational pain, and they may make a very different decision. Better context produces better judgment.
Know which context actually matters
This does not mean everyone needs every detail all the time. That would be its own failure mode, because teams can drown in context just like they can starve from the lack of it. The skill is knowing which context matters for the decision at hand. A code formatting decision does not need a history lesson. A database migration probably does. A feature flag cleanup may need to know which customers are still using the old path. A rollback plan definitely needs to know what happens to data, messages, caches, and downstream consumers. A refactor in a quiet utility library is not the same as a refactor in the middle of a production incident. Good engineers learn to sense when the visible facts are not enough.
Context transfer is the job, on both sides of the review
That instinct is valuable on both sides of the review. If you are reviewing someone else's work, ask what context you are missing before you assume the worst. If you are submitting the work, provide enough context that the reviewer does not have to reconstruct your world from a diff. A good pull request should explain more than what changed. It should explain why the change looks the way it does, call out constraints, mention tradeoffs, say what was considered and rejected, and identify the risk and the rollback path. That is not bureaucracy, that is context transfer.
A deployment pipeline is an organizational contract, and a pull request is one too, in a smaller form. It is a handoff between people who do not share the same history, and when that handoff lacks context the review becomes guesswork. Sometimes the reviewer guesses too harshly, sometimes too generously, and neither is great. The goal is not to make every engineer write a novel for every change. The goal is to stop pretending the diff tells the whole story, because it rarely does.
Systems need memory, not tribal knowledge
The same applies at the system level. Architecture decisions need memory. Not endless documents nobody reads, but enough durable context that the next team does not have to rediscover the same constraints by breaking production. Why did we choose this queue? Why is this service still on the old runtime? Why do we deploy this component separately? Why is this customer handled differently? Why does this API return that weird shape? If the only answer is ask Dave, then the system has already lost some of its memory.
That is how organizations create fragile systems protected by tribal knowledge. The context exists, but it lives in people instead of the system, and then those people become required infrastructure. You cannot scale that, and you also cannot safely improve what nobody can explain.
Where humility and responsibility meet
This is where humility and responsibility meet. Humility says I may not understand why this is the way it is. Responsibility says that once I do understand it, I am not allowed to leave the system trapped there forever. Both matter. Without humility, you break things while calling it improvement. Without responsibility, you preserve broken things while calling it respect for history. The better path is to learn the context, name the constraint, and then decide whether the constraint still deserves to exist.
Sometimes it does. A workaround for a real vendor limitation may still be necessary, a manual approval for a high-risk data migration may still be appropriate, and a strange boundary between systems may still reflect a real ownership model. But sometimes the original constraint expired years ago and nobody noticed. The customer moved, the vendor changed, the incident pattern no longer applies, the old team structure is gone, and the manual process exists only because it has always existed. That is when context becomes a tool for removal. You do not keep the workaround because there was once a reason. You remove it because you finally understand the reason and can prove it no longer applies. That is the difference between cleanup and wishful thinking.
Walk a mile, then fix what is still broken
I want engineers to be opinionated. I want them to challenge bad systems, to call out fragile deploys, unclear ownership, risky abstractions, and processes that only work when the right person is online. But I want that judgment grounded in context. The fastest way to become dangerous is to be smart, motivated, and under-informed. The fastest way to become useful is to be smart, motivated, and curious about the constraints that shaped the system before you got there. That does not mean moving slowly forever. It means spending just enough time to avoid solving the wrong problem with confidence.
Most bad engineering decisions are not made by bad engineers. They are made by engineers working with incomplete context, under real pressure, inside systems that hide the consequences until later. So before you criticize the design, walk a mile in the author's context. Then fix what is still broken.
Frequently asked questions
What does “walk a mile in my context” mean?
- It is a more operational version of walk a mile in my shoes. The shoe version is about empathy, which matters but can stay vague. The context version asks what constraints shaped a decision, what tradeoffs were visible at the time, what information was missing, what risks were known, and what pain the team was trying to avoid. Before criticizing a design, you reconstruct the world the author was working in.
Isn't a fresh perspective valuable?
- Yes, but fresh is not the same as complete. A new set of eyes often spots real problems, and it just as often underestimates why those problems exist. The failure mode is confusing fresh eyes with complete vision, seeing a local mess, and assuming the people closest to it were careless. Keep the fresh judgment, but pair it with the question: what context am I missing?
Does understanding context mean preserving bad systems?
- No. Understanding context is not surrendering to it. There is always a reason a system ended up the way it did, and bad reasons are still reasons. The point is that you cannot fix a system honestly until you understand what it was protecting itself from. Sometimes that reason still holds, and sometimes it expired years ago and nobody noticed, which is exactly when context becomes a tool for removal.
What does this have to do with AI and prompt engineering?
- A model has the same basic problem a person does: it can only reason from the context it has. Prompt engineering without context engineering is just asking a capable system to guess well. Give it a narrow slice of the world and it will optimize inside that slice, sometimes beautifully and sometimes with a clean, confident answer that is wrong for the actual situation. Better context produces better judgment, for models and engineers alike.
How should this change the way I write a pull request?
- A good pull request explains more than what changed. It explains why the change looks the way it does, calls out constraints, names the tradeoffs, says what was considered and rejected, and identifies the risk and the rollback path. That is not bureaucracy, it is context transfer. A pull request is a handoff between people who do not share the same history, and without context the review becomes guesswork.
How do you know when a workaround is safe to remove?
- You learn the context, name the constraint, and prove it no longer applies. A workaround for a real vendor limitation may still be necessary; a manual approval for a high-risk migration may still be appropriate. But customers move, vendors change, incident patterns fade, and teams reorganize. You do not keep the workaround because there was once a reason, and you do not delete it on sight either. The difference between cleanup and wishful thinking is whether you can show the original reason is gone.