Cognitive complexity is not about lines of code or cyclomatic paths. It's about how much a reader has to hold in their head simultaneously. Most codebases don't fail from lack of cleverness — they fail from too much of it.
The Problem With Clever Code
When a function requires you to track four nested conditional branches, remember three state variables, and anticipate two async operations — you've exceeded human working memory. Not because you're a bad programmer. Because you're human.
Cyclomatic complexity counts paths. Cognitive complexity measures the mental effort to traverse them. A function with cyclomatic complexity of 3 can have cognitive complexity of 12 if those paths are deeply nested and context-dependent.
What High Cognitive Complexity Actually Looks Like
Consider a function that: - Has 3 levels of nested conditionals - Uses early returns inconsistently - Mixes business logic with data transformation - References variables defined 40 lines above - Has a name that no longer reflects what it does
Each of these adds cognitive weight. Together, they make code that works but cannot be safely modified.
A Practical Reduction Strategy
Step 1: Name everything. If you can't name a block of code in 4 words or fewer, it's doing too many things. Extract it. Name it. Test it independently.
Step 2: Flatten conditionals with early returns.
Guard clauses eliminate nesting. Instead of if (isValid) { ... }, write if (!isValid) return;. Every nesting level costs cognitive load.
Step 3: Separate concerns. Business logic, data transformation, and I/O don't belong in the same function. They have different rates of change, different testing requirements, and different owners.
Step 4: Make types do the work. TypeScript's type system can encode assumptions that would otherwise live in comments or mental models. A well-typed codebase is self-documenting in the ways that matter most.
The Real Measurement
The right measurement for cognitive complexity isn't a number. It's this question: How long does it take a competent engineer, unfamiliar with this code, to make a safe change?
If the answer is more than 30 minutes for a function, the function is too complex.
What Changes When You Fix It
When I reduced average function complexity from 18 to 4 across a 40k-line codebase, onboarding time dropped from 3 weeks to 4 days. Not because the code became simpler in purpose — the business logic was just as complex. It became simpler in representation.
That's the distinction worth internalizing: complexity of the problem domain is unavoidable. Complexity of representation is entirely within your control.