
Introduction
No matter the size of the company or the maturity of the codebase, there's one question I've found myself asking time and time again when tackling a new task:
Is there an existing solution I need to augment, or do I need to solve this from scratch?
At first glance, this might seem like a simple question—just check the README, right? But in reality, it's never that straightforward.
This decision point isn't typically documented in an obvious way. It usually surfaces:
- Too late—during a PR review, when I've already built a solution.
- By accident—when a more tenured engineer sees my approach and tells me about an existing pattern I wasn't aware of.
- With luck—if the task creator had the foresight (and technical depth) to flag an existing approach in the ticket.
For new developers onboarding into a codebase, this lack of visibility can be frustrating and inefficient. Without deep insight into past decisions, how can we extract and pollinate that knowledge across the team—without relying on trial and error?
The Cost of Reinventing the Wheel
Every developer wants to build well-structured, maintainable systems. But when we lack visibility into existing solutions, we risk:
- Fragmentation – Multiple solutions to the same problem make code harder to navigate.
- Unnecessary Complexity – Reinventing logic that already exists adds cognitive overhead.
- Inconsistencies – Different implementations lead to unexpected behavior across features.
- Increased Maintenance Costs – More unique solutions mean more things to document, debug, and refactor later.
The best developers don't just write great code; they write great code that fits the existing architecture. That means knowing when to extend an existing approach versus when to introduce something new.
How to Answer the "Solve vs. Augment" Question
So, how do we equip ourselves (and new engineers) to make this decision earlier and more effectively?
Here are some practical steps I've found useful:
1. Start by Asking the Right Questions
Before writing a single line of code, I ask:
- Has this problem been solved before in our codebase?
- What similar features exist, and how were they implemented?
- Is there an existing pattern I should follow?
- If I build something new, will it conflict with anything?
If you don't know the answers, that's a red flag to dig deeper.
2. Use Git to Investigate Past Solutions
One of the most underused developer skills is code archeology—digging through history to understand why things exist.
- Search for related code: Use
git grep
,ack
, or IDE-wide searches to find similar logic. - Check commit history:
git blame
andgit log -p
show when and why certain decisions were made. - Review past PRs: Older pull requests often contain discussions on trade-offs and alternative solutions.
Instead of guessing, let the existing code tell you what the best approach might be.
3. Talk to Engineers Who Know the Codebase
No matter how good the documentation is, the best knowledge still lives in people's heads.
- Ask senior engineers: "How have we handled this in the past?"
- Post in Slack or Discord: "Is there an existing utility/method for X?"
- Review code with a team member before implementing: Catch misalignments early.
Making this a habit reduces silos and helps pollinate knowledge across the team.
4. Document "Precedent" Solutions
One of the biggest challenges for new developers is not knowing which patterns are preferred.
As a team, consider:
- Maintaining an "Architecture Decisions" doc – A simple guide to why certain approaches were taken.
- Creating a "Pattern Library" in the Wiki – Examples of common solutions (e.g., "How do we handle authentication?").
- Standardizing PR templates – Include a checklist item: "Does this follow an existing pattern?"
Making these implicit expectations explicit saves everyone time.
5. Make it Safe to Push Back on New Solutions
In an ideal engineering culture, engineers should feel comfortable saying:
- "We already have a utility for this—let's use it instead."
- "Can we solve this in a way that aligns with our existing architecture?"
- "Before merging, let's validate whether this fits with our conventions."
Encouraging pre-PR discussions and technical design reviews can prevent fragmentation before it happens.
The Balance Between Innovation and Consistency
Does this mean we should never introduce new solutions? Not at all.
New solutions are necessary when:
- Existing approaches are outdated or unscalable.
- A fundamentally different requirement emerges.
- A better, more efficient pattern is discovered.
The key is intentionality—new solutions should be introduced deliberately, not by accident.
Before creating something new, always ask:
- Does this add unnecessary complexity?
- Should we refactor an existing solution instead?
- Is this the right time to introduce a new pattern?
Consistency and innovation should coexist—but they work best when changes are made consciously, not reactively.
Conclusion
Every time I approach a new task, I ask myself:
"Am I augmenting an existing solution, or am I creating something new?"
This simple question has saved me from:
- Writing redundant code.
- Creating unnecessary complexity.
- Wasting time reinventing something that already works.
For teams looking to scale effectively, surfacing these decisions earlier is crucial. By making existing solutions more discoverable, encouraging proactive discussions, and documenting precedent, we can build more maintainable, cohesive systems—while still leaving room for innovation.
If you've ever struggled with this dilemma, I'd love to hear your approach. How does your team handle the balance between speed, consistency, and innovation?