What Is Cyclomatic Complexity? Formula, Thresholds and Tools (2026)
A practical guide to cyclomatic complexity - what it measures, how to calculate it two ways, sane thresholds, and which code review tools flag it automatically.
Published:
What is cyclomatic complexity?
Cyclomatic complexity is a software metric that counts the number of linearly independent paths through a function or method. Introduced by Thomas McCabe in 1976, it gives you a single integer that estimates how hard a piece of code is to test and reason about. A function with a complexity of 1 runs straight through with no branches. A function with a complexity of 15 has fifteen distinct routes execution can take, each of which is a place a bug can hide and a case a test needs to cover.
The reason the metric has survived for fifty years is that it correlates with two things engineers care about. First, the minimum number of test cases required to exercise every branch equals the cyclomatic complexity. Second, functions with high complexity are statistically more defect-prone, because the human mind struggles to hold many interacting conditions at once. If you want the short version to drop into a code review comment, see our cyclomatic complexity glossary entry.
How to calculate cyclomatic complexity
There are two ways to arrive at the same number. Most people learn the graph formula first and then never use it again, because the counting shortcut is faster in day-to-day work.
Method 1 - the control-flow graph formula
Model the function as a directed graph where nodes are blocks of sequential statements and edges are the jumps between them. Then:
M = E - N + 2P
Here E is the number of edges, N is the number of nodes, and P is the number of connected components (1 for a single function). This is the definition McCabe published, and it is what tools compute internally after building the control-flow graph.
Method 2 - count the decision points
For a single function you can skip the graph entirely. Start at 1, then add 1 for each of the following:
if,else if(but not a plainelse, which adds no new path)for,while,do-whileloops- each
caselabel in aswitch - each
catchclause - each
&&or||inside a condition (short-circuit operators create hidden branches) - ternary
?:expressions
Consider this Python function:
def classify_order(order):
if order.total > 1000 and order.customer.is_vip: # +1 (if) +1 (and)
return "priority"
elif order.items > 10: # +1 (elif)
return "bulk"
for item in order.items: # +1 (for)
if item.is_fragile: # +1 (if)
return "special-handling"
return "standard"
Starting at 1 and adding the five marked decision points gives a cyclomatic complexity of 6. That also tells you that you need at least six test cases to cover every path through this function.
The counting method is the one to internalize - it takes seconds, matches what your tooling reports, and doubles as a test-coverage target.
Cyclomatic complexity thresholds
The number is only useful if you know what counts as too high. The most cited guidance comes from McCabe’s original work and the NIST 235 report, which recommended 10 as a practical ceiling for most functions.
| Complexity | Interpretation | Action |
|---|---|---|
| 1 - 4 | Simple, low risk | Ship it |
| 5 - 10 | Moderate, still readable | Fine for most code |
| 11 - 20 | Complex, harder to test | Refactor when convenient |
| 21 - 50 | High risk, error-prone | Refactor before merging |
| 50+ | Untestable in practice | Break up immediately |
Treat these as conversation starters, not gates. A parser or a state machine with a flat switch over 30 token types will score 30 while remaining trivially readable. That is exactly the weakness cognitive complexity was designed to fix.
Cyclomatic vs cognitive complexity
Cyclomatic complexity treats every branch the same. But a human does not read a flat switch the way they read three levels of nested if inside a loop, even when both score the same. Cognitive complexity, introduced by SonarSource in 2018, addresses this by adding an increment for nesting depth and ignoring structures that add paths but little mental burden.
The practical takeaway - cyclomatic complexity answers “how many tests do I need,” while cognitive complexity answers “how painful is this to read.” Modern platforms report both, and when the two diverge sharply, the code usually deserves a second look. Both feed into the broader maintainability index that quality dashboards trend over time.
Which tools flag cyclomatic complexity
You should never compute this by hand in a real codebase. Every serious static analysis platform tracks it and can fail a build or PR when a function crosses a threshold.
SonarQube reports both cyclomatic and cognitive complexity per function and per file, and its quality gates let you block a merge when new code exceeds a limit you set. Because it computes complexity as part of its 6,000-plus rule engine across 35-plus languages, it is the default choice for teams that want complexity tracked alongside bugs and security findings.
CodeScene takes a behavioral angle. Instead of only reporting the current number, it overlays complexity trends on your Git history to find “hotspots” - files that are both complex and changed frequently, which is where refactoring pays off most. Its CodeHealth metric folds complexity into 25-plus factors.
Sourcery flags high-complexity functions in pull requests and suggests concrete refactors to bring the number down, with particularly strong Python support. DeepSource surfaces cyclomatic complexity among its 5,000-plus analyzers and can gate PRs on it. For a broader roundup, see our guide to the best code quality tools.
How to reduce cyclomatic complexity
When a function trips your threshold, these refactors reliably bring the number down without hiding the complexity elsewhere:
- Extract methods. Pull each cohesive branch into its own named function. The total path count across the codebase is unchanged, but each unit is now independently testable and readable.
- Replace nested conditionals with guard clauses. Return early on the invalid cases so the happy path is not buried three levels deep.
- Use a lookup table or polymorphism instead of a long
if/else ifchain that maps values to behavior. - Decompose compound boolean conditions into well-named boolean variables. This does not reduce cyclomatic complexity by itself, but it usually reveals which sub-conditions can be extracted.
The goal is never to game the metric. Splitting a 20-complexity function into two 10-complexity functions that must always be called together buys you nothing. Reduce complexity by improving structure, and let the number fall as a side effect.
Common mistakes when using the metric
- Treating it as a hard gate on all code. Generated code, parsers, and exhaustive
switchstatements legitimately score high. Whitelist them rather than contorting them. - Optimizing the number instead of the design. A low score on a badly named, poorly cohesive function is meaningless.
- Ignoring the test-case implication. If a function scores 12, your suite needs at least 12 paths covered. Complexity and code coverage should be read together, not separately.
- Measuring only cyclomatic complexity. Pair it with cognitive complexity to catch deeply nested code that the classic metric under-weights.
Conclusion
Cyclomatic complexity is a fifty-year-old metric that still earns its place because it maps directly to testability and defect risk. Learn the counting method, keep most functions at or below 10, read it alongside cognitive complexity, and let a tool like SonarQube or CodeScene track it automatically so the number surfaces in review instead of in production. The metric is not the goal - clear, testable code is. Complexity is just the fastest early warning that you are drifting away from it.
Further reading
GitarComments are not enough
Gitar applies the fix, validates it in CI, and clears the queue.
See it on your repo Read our independent Gitar reviewFrequently Asked Questions
What is cyclomatic complexity in simple terms?
Cyclomatic complexity is a count of the number of independent paths through a piece of code. In practice it equals one plus the number of decision points - if, else if, for, while, case, and each boolean operator in a condition. A straight-line function with no branches has a complexity of 1. Every branch you add creates another path that needs its own test, so the number doubles as a rough proxy for how hard the code is to test and understand.
What is a good cyclomatic complexity score?
A widely used rule of thumb from the original NIST guidance is to keep functions at or below 10. Scores of 1 to 4 are simple, 5 to 10 are moderate and generally acceptable, 11 to 20 warrant refactoring, and anything above 20 is high risk and hard to test. These are guidelines, not laws - a flat switch statement can score high while remaining perfectly readable, so use the number as a prompt to look closer, not an automatic fail.
How do you calculate cyclomatic complexity?
There are two equivalent methods. The graph formula is M = E - N + 2P, where E is edges, N is nodes, and P is connected components in the control-flow graph. The faster practical method is to start at 1 and add 1 for every if, else if, for, while, do-while, case label, catch, and each and-or-or operator inside a condition. Both give the same result for a single function.
What is the difference between cyclomatic and cognitive complexity?
Cyclomatic complexity counts paths for testability and treats every branch equally. Cognitive complexity, introduced by SonarSource, measures how hard code is for a human to read - it adds extra weight for nested structures and ignores constructs like a flat switch that add paths but little mental load. A deeply nested function can have modest cyclomatic complexity but high cognitive complexity, which is why many teams now track both.
Explore More
Tool Reviews
Free Newsletter
Stay ahead with AI dev tools
Weekly insights on AI code review, static analysis, and developer productivity. No spam, unsubscribe anytime.
Join developers getting weekly AI tool insights.
Related Articles
Is CodeRabbit Free for Open Source? Yes - And for Private Repos Too
CodeRabbit's free tier covers unlimited public and private repositories, not just open source. Here is exactly what the free plan includes, where the rate limits bite, and when to pay.
July 31, 2026
guideIs SonarLint Deprecated? No - Here's What Actually Happened
SonarLint was not deprecated. It was renamed to SonarQube for IDE on October 29, 2024, as part of a company-wide rebrand. Here is what changed, what did not, and what to install.
July 31, 2026
guideIs Semgrep Free for Commercial Use? Yes, With Two Catches
Semgrep Community Edition is LGPL-2.1 and free for commercial use. The paid tier is also free up to 10 contributors. Here is where the line actually falls and what you give up.
July 31, 2026
SonarQube Review
CodeScene Review
Sourcery Review
DeepSource Review