What is maximum nesting depth?
Nesting depth counts how many blocks — if, for, while, try — are stacked inside one another at the deepest point in a function. A function with no branching has a depth of 0 or 1 depending on how you count the outer scope. A function with an if inside a for inside another if has a depth of 3.
Why depth matters more than raw branch count
Human working memory can reliably track only a handful of things at once — the classic reference is Miller's 1956 estimate of roughly seven, plus or minus two. Each level of nesting is one more condition the reader has to keep active while parsing the innermost line: "we're inside this if, which is inside this loop, which only runs if this earlier check passed." Past four or five levels, most readers lose track and have to scroll back up to re-derive the state.
A real before/after
Nesting depth 4
def handle_order(order):
if order is not None:
if order.items:
for item in order.items:
if item.in_stock:
ship(item)
Nesting depth 1–2, guard clauses
def handle_order(order):
if order is None or not order.items:
return
for item in order.items:
if not item.in_stock:
continue
ship(item)
Nothing about what the function does changed. Every condition still gets checked. Flattening the early exits with guard clauses (return and continue) instead of wrapping the rest of the function in more if blocks removes two full levels of nesting a reader would otherwise have to track.
How deep is too deep
REPO-SIGHT flags a file once its deepest function passes a nesting depth of 6 (cpp-deep-nesting, py-deep-nesting, java-deep-nesting — same threshold across all three supported languages). In the health score, nesting depth is scored against a "good" reference of 3 and a "bad" reference of 8, at a 10% weight. It's a smaller slice of the overall grade than complexity density, but it's often the fastest single thing to fix once you spot it.
The fix pattern
- Guard clauses. Return or continue early on the failure case instead of wrapping the success case in another
if. - Extract the inner block into its own function. The nesting doesn't vanish from the codebase, but it's isolated to a well-named helper instead of buried in the middle of a larger function.
- Invert the condition. Checking for the failure case and exiting is often more readable than checking for the success case and nesting everything else inside it.