archguard checks Go modular-monolith import boundaries from a project-local config file.
It is intentionally configuration-driven: the tool knows how to load a Go import graph and evaluate a default-deny import policy, while each repository defines its own modules, layers, and allowed boundary crossings.
archguard check
archguard check --config .archguard.yaml
archguard check --dir /path/to/repo --config /path/to/repo/.archguard.yaml
archguard check --config .archguard.jsonc
archguard check --include-tests --profile modular-monolithBy default, archguard check looks for one of:
archguard.yamlarchguard.ymlarchguard.jsonc.archguard.yaml.archguard.yml.archguard.jsonc
Legacy gomodguard.* config names are not discovered; rename project configs to
one of the archguard.* names above.
JSONC config files support comments and trailing commas.
version: 1
packages:
root: github.com/example/app
patterns:
- ./internal/...
modules:
- name: orders
path: internal/orders
- name: billing
path: internal/billing
layers:
- name: domain
path: domain
- name: app
path: app
- name: ports
path: ports
- name: adapters
path: adapters
policy:
default: deny
allow:
- name: same-module
from:
module: "*"
to:
same_module: true
- name: app-to-local-domain-and-ports
from:
layer: app
to:
same_module: true
layers: [domain, ports]
- name: bootstrap-wiring
from:
path: internal/bootstrap/**
to:
internal: true
- name: app-test-support
from:
layer: app
tests: true
to:
paths:
- internal/testhelpersOptional analysis profiles enable generic AST/SQL checks without adding project-specific import rules:
analysis:
include_tests: true
profiles:
- modular-monolith
table_owners:
- module: market
tables: [wallets, wallet_clusters]
sql_table_references:
- name: migration-single-owner-statements
path: migrations/*.sql
ignore_paths:
- migrations/001_legacy_schema.sql
max_owners_per_statement: 1
external_imports:
- name: domain-production-imports
from:
layer: domain
tests: false
- name: app-production-imports
from:
layer: app
tests: false
allow:
packages:
- go.uber.org/zap
- github.com/google/uuid
protocol_boundaries:
- name: api-domain-responses
from:
path: internal/api/handlers
disallow:
layer: domain
response_sinks: [JSON, respondWithList]
request_decoders: [ShouldBindJSON]
docs: true
protocol_tags:
- name: runtime-json-tags
from:
path: internal/workers
dependency_injections:
- name: orders-foreign-store-injection
from:
path: internal/bootstrap**
field: WalletStore
consumer_module: orders
disallow:
module: accounts
forbidden_terms:
- name: vendor-terms-in-ports
from:
layer: ports
terms: [stripe, github]modulesidentify bounded contexts by repository-relative path.layersidentify conventional subdirectories within modules.policy.defaultmust bedeny; internal imports are rejected unless an allow rule matches.policy.allowentries select importers withfrom, then allow target imports withto.from.tests: truerestricts an allow rule to test import edges;from.tests: falserestricts it to production import edges; omittingtestspreserves the default behavior and matches both.to.same_moduleallows imports only when source and target are in the same configured module.to.internalallows imports to any internal package.to.module,to.modules,to.layer,to.layers,to.path, andto.pathsnarrow allowed targets.ignoreentries exclude known generated or out-of-scope paths from import checks.analysis.include_testsincludes Go test variants in import checks and profile checks.analysis.profilesenables reusable built-in checks such asmodular-monolith.analysis.table_ownersmaps table names or wildcard patterns to owning modules for SQL ownership checks when table names do not follow module-name conventions.analysis.sql_table_referencesscans configured SQL files and reports references to disallowed table owners or statements that touch more table-owner modules thanmax_owners_per_statement;ignore_pathscan baseline historical SQL files while keeping the rule active for future files.analysis.external_importsdefines an allowlist for external imports from selected packages; matching packages reject external imports not listed inallow, and omittedallowmeans no external imports are allowed.analysis.protocol_boundariesdefines transport sink/decoder/doc checks that reject configured internal types at protocol boundaries.analysis.protocol_tagsreports protocol field tags in selected packages outside transport-owned DTOs.analysis.dependency_injectionsreports configured composition-root field injections that pass dependencies from disallowed modules into another module's dependency struct.analysis.forbidden_termsreports configured vendor/protocol terms in selected packages; whenidentifiers,strings, andcommentsare all omitted, all three are checked.modular-monolithreports exportedportsAPIs that reference non-stdlib external dependency types.modular-monolithreportsportspackages that import adapter implementations.modular-monolithapplies configured protocol boundary, protocol tag, dependency injection, and forbidden term checks.modular-monolithreports exporteddomainstructs with protocol field tags such asjson.modular-monolithreports exportedappinterfaces that expose non-stdlib external dependency types.modular-monolithreports exportedportsstructs with protocol field tags such asjson.modular-monolithreports exportedportsstructs that expose primitive numeric time fields such as integer timestamps.modular-monolithreports broadportsfiles and non-persistence interfaces with large method surfaces. Persistence-shaped ports ending inRepositoryorDataSourceare excluded from this broad-surface heuristic.modular-monolithreports thin adapters that embed foreign ports or only forward calls, including cross-module local-interface wrappers.modular-monolithreports composition-root mutation, Set-style wiring, domain conversions, and SQL table references from non-owning DB-access packages or configured SQL files.
Path patterns support *, ?, and **.