Skip to main content
ArcSight

Architecture problems / High Fan-In

What is high fan-in — and when does it signal merge risk?

Fan-in is how many modules depend on a given module. High fan-in means many parts of the codebase route through the same file, type bundle, or config hub.

High fan-in is a change-risk signal, not a verdict. Shared types and config hubs often should concentrate dependencies — the question is whether you know the merge impact before you edit them.

How ArcSight detects this

Many visitors land here from search — not the homepage. Run this workflow locally on your repo.

  1. 1arc impact

    Measure merge impact on a high fan-in hub before you edit shared types or config. Example path from Payload CMS proof.

    arc impact src/typesDocs →
  2. 2arc hotspots

    Rank modules by fan-in — who depends on this?

    arc hotspots
  3. 3arc explain

    Inspect src/types — hub role, dependents, and path narrative.

    arc explain src/types
  4. 4arc watchPro

    Pro: keep architecture clean after merge so this problem does not return.

    arc watchDocs →
  • Run arc impact on the file you plan to change — blast radius and break paths surface before merge.
  • Run arc hotspots to rank modules by fan-in and downstream reach.
  • Treat modules with fan-in in the double digits on production code as change-risk zones until impact evidence is complete.

Found the issue?

Use arc impact before you change code — structured blast radius and break paths before merge. Use arc watch (Pro) to stop the problem from returning after you fix it.

All problems · Repository proofs · Install

Why it matters

Engineers search for high fan-in when a shared module feels dangerous to touch. It is a change-risk signal, not automatically bad architecture — but merge impact can surprise you if you have not traced dependents first.

What it looks like in codebases

  • A shared types or config module imported across server, client, and test packages.
  • Utility files that grow into implicit platform APIs without an explicit boundary.
  • Framework internals where dozens of feature modules depend on one router or renderer contract.

Real repository evidence3 proofs

Every row below comes from an ArcSight analysis snapshot — not a template or keyword page.

Payload CMS

Strongest fan-in signal: src/types (fan-in 225). High fan-in here is a change-risk signal — many subsystems compile against this hub.

ArcSight traced 627 modules and 2,704 edges in Payload CMS (packages/payload).

  • src/typesfan-in 225· CRITICAL risk
  • srcfan-in 154· CRITICAL risk
  • src/config/typesfan-in 142· CRITICAL risk
  • src/collections/config/typesfan-in 128· CRITICAL risk
  • src/fields/config/typesfan-in 124· CRITICAL risk
  • src/errors/APIErrorfan-in 41· blast radius 495
  • src/versions/typesfan-in 16· blast radius 477
  • src/utilities/isNumberfan-in 14· blast radius 477

Inspect first: src/types · src · src/config/types

Full repository proof: /repositories/payload/

Next.js

Strongest fan-in signal: src/server/config-shared (fan-in 46). High fan-in here is a change-risk signal — many subsystems compile against this hub.

ArcSight traced 1,942 modules and 4,489 edges in Next.js (packages/next).

  • src/server/config-sharedfan-in 46· blast radius 423
  • src/shared/lib/app-router-typesfan-in 45· CRITICAL risk
  • src/shared/lib/segmentfan-in 23· HIGH risk
  • src/typesfan-in 21· blast radius 423
  • src/server/lib/lru-cachefan-in 12· HIGH risk

Inspect first: src/server/config-shared · src/shared/lib/app-router-types · src/shared/lib/segment

Full repository proof: /repositories/nextjs/

Directus

Strongest fan-in signal: src/logger (fan-in 104). High fan-in here is a change-risk signal — many subsystems compile against this hub.

ArcSight traced 789 modules and 2,287 edges in Directus (api).

  • src/loggerfan-in 104· CRITICAL risk
  • src/constantsfan-in 34· blast radius 345
  • src/cachefan-in 25· blast radius 340
  • src/utils/get-config-from-envfan-in 16· CRITICAL risk
  • src/busfan-in 15· blast radius 401
  • src/utils/get-millisecondsfan-in 14· blast radius 354
  • src/permissions/modules/process-ast/typesfan-in 11· blast radius 350
  • src/utils/get-default-index-namefan-in 9· blast radius 341
  • src/redisfan-in 8· CRITICAL risk
  • src/redis/lib/create-redisfan-in 2· CRITICAL risk
  • src/redis/lib/use-redisfan-in 1· CRITICAL risk

Inspect first: src/logger · src/constants · src/cache

Full repository proof: /repositories/directus/

What to inspect first

  • The module with the highest fan-in in the subsystem you are changing.
  • Public exports on that module — every export is a contract someone downstream may rely on.
  • Impact paths from arc impact before splitting, renaming, or narrowing types.

What to do next

  • Inspect impact paths on the highest fan-in module before refactoring shared types or config.
  • Stabilize the public surface of hub modules — split optional helpers out of core type authorities.
  • Re-run arc impact after each boundary change; refusal means stop until evidence is complete.

Install · Validation · Repository proofs