Image represents a media kit with boilerplate, logos and more

Definition and Guide

Cyclomatic complexity: developer's guide

Cyclomatic complexity serves as a vital gauge in software development, quantifying a program's complexity by counting its independent paths. Monitoring this metric enables the pinpointing of problematic code sections prone to errors, facilitating easier maintenance and overall robustness of software applications.

Table of Contents

Start your free trial

Verify all code. Find and fix issues faster with SonarQube.

Get started

Modern software development today spans distributed teams, interconnected services, and rapidly evolving requirements—and at the center of it all is the code holding these systems together. When that code is structured with lower complexity, it becomes far easier to understand, reason about, and maintain. A clear grasp of your codebase directly contributes to higher quality, better testability, and fewer long-term issues.

Cyclomatic complexity offers a quantitative way to measure this structural complexity by counting the number of linearly independent paths through a program’s control flow. Monitoring this metric helps you pinpoint areas that may be overly intricate or error-prone, allowing you to refactor early and reduce maintenance risks. In this post, we’ll break down what cyclomatic complexity is, how it’s calculated, why it matters, and which tools can help you analyze and manage it effectively.

What is cyclomatic complexity?

Cyclomatic complexity is a software engineering metric that was introduced by Thomas J. McCabe in 1976. This metric is a numerical score that represents the number of different paths a program can take during its execution. A higher score means more execution paths (higher complexity), while a lower score means fewer paths (lower complexity).

Programs with high cyclomatic complexity tend to be more prone to errors and harder to test and maintain. On the other hand, a lower cyclomatic complexity value suggests that the program is highly readable and easier to understand, test, and modify.

By quantifying the complexity of a program, developers are better prepared to approach and prioritize code modifications, refactoring, and testing. When it comes to managing larger codebases—where the risk of bugs increases with complexity—the cyclomatic complexity metric becomes especially useful.

Why is cyclomatic complexity important?

Cyclomatic complexity is more than just a software-engineering metric—it’s a practical lens for understanding the structural complexity of your code. By measuring the number of linearly independent paths through a program’s control-flow graph, it highlights how many decision points, branches, and execution paths exist in your functions, modules, or classes. The higher this number climbs, the harder the code becomes to read, test, and maintain.

High complexity is strongly correlated with increased defect risk, because code with many branches is more error-prone and requires significantly more test cases for adequate path coverage or basis path testing. This relationship makes cyclomatic complexity a powerful indicator of maintainability issues and potential bug hotspots. It draws directly on principles from graph theory, treating a program’s flow as a network of nodes, edges, and independent cycles, which helps teams reason about the internal structure of their logic.

Why cyclomatic complexity is important:

  • Improved maintainability and readability: Lower complexity scores indicate simpler code, which is easier to read, understand, and modify. It acts as a guide for when code has become too complex and needs to be broken down (refactored).
  • Enhanced testability (Quality Assurance): The metric directly correlates to the number of test cases required for full branch coverage. A higher score means more paths need testing, helping QA teams identify where to focus efforts.
  • Risk management and reduced bugs: Complex code is more error-prone. High complexity scores (e.g., above 20) often signal that a function has too many decision points, indicating a higher risk of bugs in production.
  • Targeted refactoring: It identifies "bumpy roads" or convoluted logic that could be split into smaller, more manageable functions, reducing technical debt. 

What is the formula for cyclomatic complexity?

The formula to calculate cyclomatic complexity is relatively straightforward. Start by observing the program’s control-flow graph—a graphical representation of all paths that might be traversed through a program during its execution.

An image that describes the formula for cyclomatic complexity.
  1. Control-flow graph examples of simple programming scenarios
    (a) if-then-else statement
    (b) while loop
    (c) a natural loop with an if statement break in the middle
    (d) a loop with two entry points

Source

Looking at a control-flow graph, we would represent the number of edges in the graph as E, while N represents the number of nodes in the graph.

The formula for cyclomatic complexity C is:

C = E - N + 2P

where P represents the number of connected components. For a single program, P = 1.

This calculation gives us the number of linearly independent paths through the code. It indicates the minimum number of paths that you need to test to ensure each decision point is executed at least once. When C is high, then you have more complex code with more paths—meaning potentially higher maintenance and testing effort.

A simple conclusion we can draw from considering cyclomatic complexity is this: if, while, for, or switch statements add complexity because each condition introduces a new path in the flow of the program. As a developer, you can look at this formula and quickly gauge the complexity of any part of your program.

Understanding and applying this formula will help you keep your code clean, efficient, and maintainable.

What is an example of cyclomatic complexity?

To illustrate cyclomatic complexity with a practical example, let's look at a basic piece of code written in JavaScript. This example will help us understand how cyclomatic complexity is calculated and why it matters.

This straightforward JavaScript function checks if a user is eligible for a discount based on various conditions:

function checkDiscount(age, membershipDuration) {
  let discount;
  if (age > 60) {
    discount = 25; // Senior discount
  } else if (membershipDuration > 5) {
    discount = 15; // Loyalty discount
  } else {
    discount  0; // No discount
  }
  return discount;
}

We can represent these lines of code with the following control flow graph:

Let’s walk through how we would calculate cyclomatic complexity.

First, let’s look for decision points in the function. In our example, there are two conditions:

  • if (age > 60)
  • else if (membershipDuration > 5).

Each decision point can lead to different outcomes:

  • The condition age > 60 is true
  • The first condition is false, but membershipDuration > 5 is true.
  • Both conditions are false.

As we look at the control-flow graph, our total number of edges is 8. Our total number of nodes is 7. And because the entire function is a single connected component, P = 1. When we apply the formula, we get this:

C = E - N + 2P

= 8 - 7 + 2(1)

= 3

This cyclomatic complexity score of 3 indicates that there are three distinct paths through the code. Each of these paths must be tested to ensure all scenarios are covered. By breaking down our code methodically like this, we clarify what’s needed for software testing and highlight the complexity in our code—complexity that could potentially be simplified.

How to test cyclomatic complexity

Testing cyclomatic complexity, stated simply, means ensuring that you’ve adequately tested all of the possible paths in your program. Adequate test code coverage is important if you want to keep your code quality and reliability high.

After you have calculated the cyclomatic complexity of your code, break down your code to identify what those paths are. Here’s a tip: Each decision point in your code (such as conditional statements or loops) usually contributes to a new path.

Once you’ve identified your paths, create test cases for each one. The goal is to execute each path at least once. This ensures that all the functional aspects of the code are tested, and it will help you in catching potential errors in code logic. Use automated testing tools to run your test cases. After analyzing the test results, check for any failures or unexpected behaviors. Each failed test case might indicate a bug or a flaw in that path of your source code.

If all your tests are passing but you feel like the cyclomatic complexity is too high, then you can consider refactoring the code to simplify it. This might involve breaking down complex functions into simpler ones or reducing the number of decision points. After refactoring, repeat the testing process to ensure the new code maintains or improves quality.

By regularly determining cyclomatic complexity and then testing your code accordingly, you can maintain a manageable level of complexity. This simplifies the testing process and your codebase, leading to more reliable and maintainable software.

How to do cyclomatic complexity analysis

Cyclomatic complexity code analysis involves reviewing your program’s source code to understand its structure and identify areas where the complexity can be reduced. To do this, you would start by gathering all the source code that needs analysis. This might be a specific module or a set of functions—or maybe even an entire application—depending on your focus. You can use tools like static code analyzers to automate the process of calculating cyclomatic complexity for each function or module. These tools will help you in providing a quick overview of your code complexity.

From there, identify any parts of code with high complexity scores. These are the areas that may be potentially difficult to understand, test, and maintain. Prioritize areas that should be refactored. Determining which areas those are will depend on their complexity and the criticality of their functionality within the application. Focus on areas where reducing complexity will yield significant benefits for maintainability and reliability.

As you refactor and the cyclomatic complexity decreases, you may find that your number of test cases also decreases. After refactoring, rerun your tests (which also have been rewritten) to ensure you haven’t broken anything. Then, recalculate the cyclomatic complexity to ensure that your changes have effectively reduced the complexity.

By regularly performing cyclomatic complexity analysis, development teams can proactively manage their codebase, ensuring that it remains clean, testable, and maintainable. This practice will help you improve code quality, and it’ll ultimately make your development processes more efficient.

Limitations & pitfalls of cyclomatic complexity

While cyclomatic complexity is a useful metric, it doesn’t always reflect how maintainable code truly is. A function with minimal branching can still be difficult to work with if it’s long, deeply nested, or packed with complex expressions. Likewise, readability, naming, and overall structure—factors that strongly influence maintainability—are not captured by the metric. This means two pieces of code with the same complexity score can differ greatly in how easy they are to understand or modify.

Cyclomatic complexity can also be misinterpreted or even unintentionally “gamed.” Splitting large functions into many small ones may reduce individual complexity scores but still leave behind a high number of execution paths across the module. Some codebases also artificially lower complexity by flattening branching, even when doing so reduces clarity. To get a fuller picture, teams often pair cyclomatic complexity with complementary metrics like Cognitive Complexity, which accounts for how difficult code is to read and mentally process. Together, these metrics provide a more accurate view of real-world code quality.

What are tools and software for cyclomatic complexity?

Identifying and dealing with code areas with high cyclomatic complexity is crucial for maintaining high-quality, maintainable software. Many tools and software solutions are available to help developers assess and monitor this complexity.

  • SonarQube Server is a comprehensive code quality tool that integrates directly into your development workflow. It provides detailed reports on cyclomatic complexity, among other software metrics. SonarQube Server helps identify complex code that might need refactoring and supports 30+ programming languages (including Java, Python, Go) and frameworks.
  • SonarQube Cloud is a cloud-based service that provides automated code review for complexity analysis. This is particularly useful for continuous integration/continuous deployment (CI/CD) and DevOps platform environment, offering real-time feedback on code changes and their impact on complexity.
  • SonarQube for IDE is an IDE plugin that provides on-the-fly feedback to developers as they write code, helping them to maintain low complexity from the start. It can be used in popular IDEs like Visual Studio, Eclipse, and IntelliJ IDEA.

These tools provide valuable insights into code complexity, helping teams make informed decisions about where to focus their refactoring efforts to improve maintainability and simplify debugging.

Language-specific considerations

Cyclomatic complexity follows the same formula across languages, but its meaning can vary depending on the language’s syntax and style. In imperative languages like Java, C#, or Python, complexity rises mainly through explicit branching—if statements, loops, switch blocks, and exception handling. Other features, such as short-circuit logic or comprehensions, can also add hidden paths that aren’t always obvious at first glance.

Functional and hybrid languages introduce their own quirks. Lambdas, closures, recursion, and pattern matching may produce fewer visible branches while still encoding dense logic that’s harder to reason about. As a result, the same numeric complexity score may indicate very different levels of difficulty depending on the paradigm. Understanding these differences helps teams interpret the metric accurately and decide when high complexity truly signals a maintainability risk.

Conclusion

Understanding and managing cyclomatic complexity is important if you want to develop clean and high-quality software. This metric serves as a guide for developers to identify areas that may be prone to errors or difficult to maintain. By regularly measuring and analyzing cyclomatic complexity, you can ensure your code is both efficient and maintainable.

To get started using tools that will help keep your cyclomatic complexity low and your software quality high, use SonarSource tools for free today.

  • Follow SonarSource on Twitter
  • Follow SonarSource on Linkedin
language switcher
English

© 2025 SonarSource Sàrl. All rights reserved.