Go's module system is one of the more disciplined dependency caching designs in mainstream use — content-addressed, immutable, verified by checksum on every use — which also means it accumulates in a very predictable way. Once you understand the two directories involved and what each one is for, deciding what to clean up is a short exercise rather than a guessing game.

GOPATH versus GOMODCACHE: two different things

Before Go modules existed (pre-1.11), all Go code and dependencies lived under a single GOPATH directory, by convention ~/go. Since modules became the default, GOPATH still exists and still defaults to ~/go, but its role narrowed — it now mainly holds the module cache and any binaries installed via go install, rather than being where your own project source has to live.

GOMODCACHE is a more specific variable, defaulting to $GOPATH/pkg/mod — that is, ~/go/pkg/mod under the default GOPATH. This is where every downloaded module version actually lives. You can check both on your machine directly:

go env GOPATH
go env GOMODCACHE

If you haven't customised either, they'll both point at the expected defaults, with GOMODCACHE nested inside GOPATH.

What's inside ~/go/pkg/mod

The module cache stores, for every module version any Go project on your machine has depended on:

  • The module's source files, extracted and ready to compile against.
  • A cached copy of the module's go.mod file and other metadata.
  • Cryptographic hashes used to verify the module's content hasn't changed since it was first downloaded — Go checks this on every build, which is part of why Go's dependency model is considered unusually tamper-resistant compared to some other ecosystems.

Because modules are versioned and immutable by convention (a published version's content is not supposed to change after the fact, and Go's checksum verification would catch it if it did), the cache is safe to keep indefinitely and safe to delete entirely — there's no "stale metadata" class of problem here the way there is with, say, Maven's mutable SNAPSHOT versions.

Check the size:

du -sh ~/go/pkg/mod

For a machine with a few years of active Go development, especially across projects with heavy dependency trees (Kubernetes-adjacent tooling and cloud SDKs are notorious for pulling in large transitive dependency graphs), this can reach several gigabytes.

go clean -modcache

go clean -modcache

This deletes the entire module cache. The next go build or go test for any project re-downloads whatever modules it needs from the configured module proxy (by default, Google's public proxy, though this is configurable via GOPROXY and often pointed at a private proxy in corporate environments). Because Go modules are cached by exact version and verified by checksum, there's no correctness risk to clearing this — only the time cost of re-downloading.

One detail worth knowing: some files in the module cache are made read-only by Go deliberately, to discourage accidental modification of what's supposed to be immutable, verified content. go clean -modcache handles this correctly on its own; a manual rm -rf ~/go/pkg/mod may hit permission errors on some files unless you adjust permissions first, which is one good reason to prefer the built-in command over a manual delete here.

Per-project vendor/ folders are a different, opt-in mechanism

Separately from the shared module cache, a Go project can maintain a vendor/ directory — a complete, project-local copy of all its dependencies' source, committed to the repository itself (via go mod vendor). This is an opt-in pattern some teams use for build reproducibility independent of network access to a module proxy, or for regulatory reasons requiring vendored dependency source under version control.

If a project uses vendor/, that folder is not a cache in the disposable sense — it's checked-in project data, and Go will actually build from it directly when a vendor/modules.txt is present, rather than consulting GOMODCACHE at all for that project. Don't casually delete a vendor/ folder the way you would the shared module cache; check whether it's committed to git first (git ls-files vendor shows entries if it is).

The build cache is a separate thing entirely

Go also maintains a completely separate compiler build cache — cached compiled object files, keyed by source content and build flags — used to speed up repeated builds of your own code, distinct from the module cache which only holds third-party dependency source. This lives under a location reported by:

go env GOCACHE

(typically ~/Library/Caches/go-build on macOS). It can be cleared independently:

go clean -cache

Clearing the build cache and clearing the module cache address different things — the build cache affects how fast your own code recompiles, while the module cache affects how fast dependencies resolve and download. If you're chasing down a specific stale-build symptom rather than reclaiming disk space, go clean -cache is the more targeted tool of the two.

Private module proxies and GOPRIVATE change the download path, not the cache format

If your organisation runs an internal module proxy (common for private, unpublished Go modules that shouldn't be resolved through the public proxy), the GOPRIVATE and GONOSUMCHECK-adjacent settings change where modules are fetched from and whether checksum verification against the public sum database applies, but they don't change how the local cache itself is structured or cleaned — ~/go/pkg/mod still ends up holding the same kind of content regardless of which proxy served it, and go clean -modcache clears all of it uniformly whether a given module came from the public proxy, a private one, or a direct VCS fetch.

This is worth knowing mainly so you don't assume a corporate proxy setup requires different cleanup commands — it doesn't. The only practical difference after a full cache clear is where the next download comes from, which may matter for speed or for internal network dependency but not for the cleanup process itself.

Module cache size scales with how many major versions you've touched

Go's module system treats different major versions of the same module as entirely separate module paths by convention (github.com/example/lib versus github.com/example/lib/v2), which means the cache doesn't naturally consolidate across a project's major version upgrades the way a simpler versioning scheme might. A machine that's built against several major-version generations of a popular dependency across different projects over the years accumulates each major version's full set of minor and patch releases independently, which is one of the less obvious contributors to a larger-than-expected GOMODCACHE.

A practical routine

  1. go env GOMODCACHE and go env GOCACHE to confirm both locations on your machine.
  2. du -sh each to see current size.
  3. For general disk pressure, go clean -modcache reclaims the module cache safely; follow with go clean -cache if the build cache is also large.
  4. Check any project you maintain for a committed vendor/ folder before assuming it's disposable — treat it as project data, not cache, if it's under version control.

Where VolumeLens fits in

Go's module cache is one of the more well-behaved caches on a typical Mac — predictable location, safe to clear entirely — but it still competes with everything else on disk for attention, and it's easy to forget it's there until a go build fails from lack of space rather than from a code problem. VolumeLens shows ~/go/pkg/mod sized honestly alongside every other developer cache on your Mac, so you know at a glance whether it's worth reclaiming. Try the free scan on your own machine.