Module boundaries
moduleBoundaries enforces architectural constraints by preventing files in certain directories (or patterns) from importing files in other forbidden directories.
What this check does
The check looks at files matching a specific pattern and analyzes their import statements. If any of these imports match a pattern listed in the deny list, a violation is reported. You can also use the allow list to permit specific exceptions to a broader deny rule.
Why it is important
Maintaining clear boundaries is crucial for the long-scale health of a codebase:
- Architectural Integrity: It prevents "spaghetti dependencies" where any part of the system can import any other part, leading to an unmanageable dependency graph.
- Layer Separation: It ensures that higher-level layers (like UI) cannot depend on lower-level implementation details (like database internals) that should be hidden.
- Feature Isolation: It helps maintain the independence of features or packages, making them easier to test, refont, or even extract into separate repositories.
- Monorepo Governance: It is highly effective for enforcing boundaries between monorepo packages, such as preventing a mobile app package from accidentally importing server-side logic.
It's especially important in an increasingly agentic development landscape, preventing AI agents from introducing structural regressions or violating design principles they may not be contextually aware of.
Module Boundaries vs. Restricted Imports
It is important to distinguish moduleBoundaries from restrictedImports.
moduleBoundariesis centered on colocation and patterns. It checks the relationship between files based on their paths: "If a file matching pattern A imports a file matching pattern B, it is a violation." It works on a file-to-file level.restrictedImportsis centered on reachability and entry points. It starts from a set of defined entry points and traces the dependency graph, looking if any unwanted file path path is imported transitively. It works on an dependency graph level.
Configuration
Below is an example of how moduleBoundaries fits within the rules array:
{
"rules": [
{
"path": ".",
"moduleBoundaries": [
{
"name": "ui-cannot-import-api",
"pattern": "src/ui/**",
"deny": ["src/api/**"]
},
{
"name": "feature-isolation",
"pattern": "src/features/auth/**",
"deny": ["src/features/payment/**"]
}
]
}
]
}
Options
Each boundary rule consists of:
name(string): A descriptive name for the boundary rule.pattern(string): The glob pattern defining which importing files belong to this boundary.deny(array of strings): A list of glob patterns that are forbidden for the files matching thepattern.allow(array of strings, optional): A list of glob patterns that are explicitly permitted, overriding thedenylist for specific cases.
Also referred as
Module Boundary Enforcement is also known as:
- Module boundaries
- Dependency boundaries
- Architectural boundaries
- Layer separation enforcement
- Prohibited imports between modules
- Enforce Module Boundaries
- Monorepo Dependency Management