Boring Over Clever: Why Simple Code Wins at 3am
It's 3am. Something is broken in production. You open the file and see this:
const getUser = (id: string) =>
pipe(
id,
validateId,
fetchFromCache,
orElse(fetchFromDB),
map(transformUser),
tap(logAccess),
getOrElse(null)
);Clever. Functional. Completely unreadable when your eyes are half-open and your coffee is cold. You added this 3 months ago. You have no idea what orElse does right now. The cache is broken somewhere in this pipeline and you can't tell where.
Now imagine the boring version:
async function getUser(id: string) {
if (!isValidId(id)) return null;
const cached = await cache.get(id);
if (cached) {
logAccess(id);
return transformUser(cached);
}
const user = await db.users.findById(id);
if (!user) return null;
logAccess(id);
return transformUser(user);
}Twelve lines. Every step visible. You can put a console.log anywhere. You can comment out the cache check in 2 seconds. At 3am, boring code is a gift you gave your future self.
What makes code "clever"
Clever code optimises for the author's satisfaction, not the reader's understanding. It reaches for abstraction before the use case demands it. It chains operations that should be steps. It uses a design pattern where an if-statement would do.
Common clever traps:
- Functional pipelines for sequential steps that need to be debuggable
- Generic utilities that handle 10 cases when you have 2
- Recursive solutions for loops that work fine
- One-liners that need a comment to explain what they do
The rule: if you need a comment to explain WHAT the code does (not why), rewrite it until the code explains itself.
Real example: a "smart" debounce hook
A junior on a team built this for a search input:
function useSmartDebounce<T>(
value: T,
delay: number,
comparator: (a: T, b: T) => boolean = Object.is,
onFlush?: (value: T) => void
): [T, boolean] {
const [debouncedValue, setDebouncedValue] = useState(value);
const [isPending, setIsPending] = useState(false);
const prevValue = useRef(value);
useEffect(() => {
if (comparator(prevValue.current, value)) return;
setIsPending(true);
const timer = setTimeout(() => {
setDebouncedValue(value);
setIsPending(false);
onFlush?.(value);
prevValue.current = value;
}, delay);
return () => clearTimeout(timer);
}, [value, delay, comparator, onFlush]);
return [debouncedValue, isPending];
}The actual usage in the codebase, one place, one use case:
const [query] = useSmartDebounce(inputValue, 300);The boring version for that one use case:
const [query, setQuery] = useState('');
useEffect(() => {
const timer = setTimeout(() => setQuery(inputValue), 300);
return () => clearTimeout(timer);
}, [inputValue]);Six lines. Does exactly what the codebase needs. No comparator, no isPending, no onFlush. Those features don't exist in the requirements. They exist in the junior's imagination of what requirements might appear.
Boring is harder than clever
This is the counterintuitive part. Writing boring code takes more discipline than writing clever code. Clever code is a natural reflex. You see a pattern, you abstract it, it feels good. Boring code requires you to actively resist that reflex.
The question to ask: "Could someone who joined this team yesterday understand this without asking me?" If the answer is no, make it more boring.
When clever is actually right
Not all cleverness is bad. Clever at the algorithm level (a well-chosen data structure, an efficient sort) is different from clever at the API level. A binary search is clever; a pipeline of map/filter/reduce/pipe is not.
The test: clever code that is well-understood by the entire team, documented, and in a stable part of the codebase is fine. Clever code that only the author understands, in a hot path that changes often, is a liability.
The 3am test
Before committing, ask: if this breaks at 3am and I'm half asleep, can I find and fix the bug in under 10 minutes?
If the answer is no, make it more boring. Your future self will thank you.
Recommended for you
- QualityClaude Code
AI Agents Are the Most Expensive Junior Devs You'll Ever Hire
The same over-engineering reflex that costs a team two days of junior time now costs you an hour of agent output, multiplied across every PR. The tax rate did not change. The volume did.
- QualityClaude Code
When AI Agents Split Your Codebase Into Too Many Files
The agent's PR has six new files for one small feature. A utils file for one function. A types file for two interfaces. An index.ts that re-exports everything. None of it earns its keep.
- QualityClaude Code
Stop Building What Already Exists: The Lazy Dev Mindset
Every junior dev I've met tries to build what already exists. Here's how the "laziest solution that works" mindset, backed by real code, makes you a better developer, faster.
Enjoyed this article?
Subscribe for new articles. No spam. Unsubscribe anytime.
By subscribing you agree to receive the newsletter. See the Privacy page.