YAGNI (you aren't gonna need it)
YAGNI (You Aren't Gonna Need It) - a development principle that says only implement what the current spec requires, and add more only when a real need arrives.
Theory
TL;DR
- Analogy: build the kitchen now, not the chef's pantry you might want someday.
- Core rule: "Does the spec demand it today?" If no, skip it.
- Main cost: teams waste 20-30% of dev time on features nobody ever uses.
- YAGNI vs DRY: DRY removes current duplication; YAGNI blocks speculative future code.
- Break it for security basics and proven structural patterns like MVC skeleton.
Quick example
// Task: filter users by active status. Nothing else in the spec.
// YAGNI violation - sorting and pagination added "for later"
function getActiveUsersBad(users, page = 1, sortBy = 'name') {
return users
.filter(u => u.active) // needed
.sort((a, b) => a[sortBy].localeCompare(b[sortBy])) // not needed yet
.slice((page - 1) * 10, page * 10); // not needed yet
}
// YAGNI: do exactly what the spec says
function getActiveUsers(users) {
return users.filter(u => u.active);
}
// Output: [{ name: 'Alice', active: true }, { name: 'Bob', active: true }]The bad version isn't just verbose. It adds code nobody will test, maintain, or probably ever call.
Why it matters
Speculative features cost twice: once to write, once to maintain when real requirements change. That second hit is the painful one, because you're refactoring code that never served a single user. I've seen a user roles table built before launch and deleted two weeks later, zero users ever touched it, two days gone. The 20-30% waste estimate from teams that ignore YAGNI is conservative. Anyone who has cleaned up a codebase full of "just in case" abstractions knows how bad it gets.
One clarification worth making: YAGNI doesn't mean never plan ahead. It means don't write the code until the need is proven.
When to use
- Spec lacks the feature: skip it. Write it when the ticket arrives.
- User story says "maybe later": implement the minimum that works now.
- Prototype phase: smallest thing that tests the hypothesis.
- Refactor pass: add a feature only if metrics show a real bottleneck.
Common mistakes
Adding config params "just in case"
// Wrong - three params nobody asked for
function filterUsers(users, active = true, minAge = 0, country = '') {
return users.filter(
u => u.active && u.age >= minAge && (country ? u.country === country : true)
);
}
// Right - spec said "active users only"
function filterUsers(users) {
return users.filter(u => u.active);
}Adding params now means writing tests for them, keeping them in docs, and explaining them to every new dev. Add them when a ticket demands it.
Over-abstracting for hypothetical plugins
// Wrong - base class for plugins that don't exist yet
class UserFilter {
process(users) {} // empty method waiting for "someday"
}
// Right - just a function
function filterUsers(users) {
return users.filter(u => u.active);
}A common story: a dev builds a plugin system on day one, it's never extended, and six months later every real feature has to work around the unused abstraction.
Prebuilding infrastructure for unproven scale
Adding a Redis queue for a service handling 10 users per day creates immediate ops overhead with zero guaranteed payoff. The sequence is: in-memory array first, then a database, then a queue - only after load tests show you actually need it.
Speculating on UI states
Unused tabs, disabled buttons with no spec, loading states for features not yet built. All of it becomes dead code that junior devs debug without any context.
Real-world usage
- React:
create-react-appships with minimal defaults. No TypeScript, no Redux, no routing until you add them. - Express: start with a base router. Add rate limiting after a real security review, not before.
- Redux: add actions only for live features. No "future offline mode" sagas upfront.
- Node CLI tools:
fs.readFileSyncworks fine until profiling shows a bottleneck. Then switch.
Follow-up questions
Q: What is YAGNI?
A: A principle that says build only what the current spec requires. If the need isn't proven, the code doesn't exist yet.
Q: How does YAGNI differ from DRY?
A: DRY removes duplication in code that already exists. YAGNI stops you from writing code that doesn't need to exist at all.
Q: When is it okay to break YAGNI?
A: For proven patterns like MVC structure or input sanitization. Security basics always apply, even before users ask for them.
Q: How do you measure whether a feature is actually needed?
A: Track user tickets and usage metrics. If fewer than 5% of users request something over three months, it probably doesn't belong in the next sprint. Senior devs tie this to OKRs.
Q: Can YAGNI conflict with agile planning?
A: Not if you treat each sprint as an MVP cycle. Use spike stories for genuine unknowns. Everything else ships only when a user story proves the need.
Examples
Basic: YAGNI in an Express endpoint
// Spec: return active users with a valid email. Nothing else.
app.get('/api/users', (req, res) => {
const activeUsers = users.filter(u => u.active && u.email);
res.json(activeUsers);
});
// GET /api/users → [{ id: 1, name: 'Alice', active: true, email: 'a@test.com' }]
// No auth, no pagination - spec doesn't ask for it yet.This endpoint does exactly what the current spec says. Auth gets added when the security ticket arrives, not before.
Intermediate: sort on demand, not upfront
// Users requested sorting after launch. No need to prebuild it.
function UserList({ users }) {
const [sortBy, setSortBy] = useState(null); // null until the user clicks
const sorted = sortBy
? [...users].sort((a, b) => a[sortBy].localeCompare(b[sortBy]))
: users; // no sort logic runs until needed
return (
<div>
{sorted.map(u => <div key={u.id}>{u.name}</div>)}
<button onClick={() => setSortBy('name')}>Sort by name</button>
</div>
);
}The sort exists because users actually asked for it after launch. Before that, the component shipped without it. Adding it later took one afternoon, not a week of refactoring a pre-built sort system.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.