go mod download vs go mod tidy: Key Differences and When to Use Each

The primary difference is that go mod download populates the local module cache without modifying module definitions, while go mod tidy cleans up go.mod and go.sum by adding missing dependencies and removing unused ones.

Both commands operate on a module’s dependency graph, but they serve distinct purposes within the Go toolchain. According to the golang/go source code, understanding the architectural separation between cache management and dependency graph maintenance is essential for efficient CI pipelines and reproducible builds.

Core Functional Differences

go mod download focuses exclusively on fetching and verifying module contents. It parses the existing go.mod file to identify required modules, then ensures their source code is present in the local module cache ($GOMODCACHE). The command never adds or removes require statements from go.mod, though it will append checksum entries to go.sum for any newly downloaded modules.

go mod tidy performs dependency graph maintenance. It scans the source tree to discover imported packages, computes the minimal set of required modules, and reconciles that set with the current go.mod. This process may add new require statements, drop unused ones, and prune irrelevant exclude or replace directives. Finally, it regenerates go.sum to contain checksums exactly for the modules required by the final go.mod, removing any stale entries.

How go mod download Works

The implementation resides in [src/cmd/go/internal/modcmd/download.go](https://github.com/golang/go/blob/master/src/cmd/go/internal/modcmd/download.go). When executed, the command follows this flow:

  1. Parse Requirements: Reads the current go.mod to obtain the list of required modules.
  2. Fetch Modules: Invokes modfetch.DownloadModule (defined in src/cmd/go/internal/modfetch/fetch.go) for each module entry.
  3. Cache Population: Resolves the module version, contacts the configured proxy or cache, verifies the checksum against go.sum, and stores the module zip and source files in $GOMODCACHE.
  4. Output: If -json is supplied, emits a ModuleJSON struct (lines 94–112 in download.go) describing the download result.

# Pre-populate the cache for all dependencies listed in go.mod

go mod download

# Download a specific version with machine-readable output

go mod download -json golang.org/x/tools@latest

How go mod tidy Works

The logic lives in [src/cmd/go/internal/modcmd/tidy.go](https://github.com/golang/go/blob/master/src/cmd/go/internal/modcmd/tidy.go). This command orchestrates the tidy algorithm from the modload package:

  1. Load Graph: Calls modload.LoadAllModules to initialize the module loading system.
  2. Source Analysis: Walks the source tree to discover all imported packages and computes the minimal required module set.
  3. Reconcile Dependencies: Compares the computed set against the existing go.mod, adding missing require statements and removing unused ones.
  4. Write Changes: Invokes modload.WriteGoMod to rewrite go.mod and modload.WriteGoSum to generate a clean go.sum containing only the necessary checksums.

Unlike go mod download, go mod tidy accepts no arguments and always operates on the module in the current directory.


# Clean up go.mod and go.sum after removing an import

go mod tidy

When to Use Each Command

Use go mod download when you need to:

  • Pre-populate the module cache before running tests or CI steps that require dependency source code.
  • Verify that a specific module version can be fetched from the proxy.
  • Populate $GOMODCACHE in a Docker layer without modifying build files.

Use go mod tidy when you need to:

  • Ensure the module’s dependency list is accurate after adding or removing code imports.
  • Keep go.mod and go.sum minimal and reproducible before committing changes.
  • Prune unused dependencies that are no longer referenced by the codebase.

Summary

  • go mod download only reads go.mod to fetch modules into $GOMODCACHE, never modifying the module definition itself.
  • go mod tidy actively modifies go.mod and go.sum to reflect the actual imports used in the source code.
  • Download appends to go.sum but never deletes entries; tidy regenerates go.sum to match the final dependency set exactly.
  • Download accepts specific module arguments and supports -json output; tidy works only on the current directory module.

Frequently Asked Questions

Does go mod download update the go.mod file?

No. According to the implementation in download.go, the command only reads the existing go.mod to determine which modules to fetch. It never adds or removes require statements, though it may append new checksum entries to go.sum for modules that were not previously recorded.

Can go mod tidy be run with specific module arguments?

No. The go mod tidy command takes no arguments and always operates on the module in the current working directory. It scans the entire source tree to determine the complete set of required dependencies before updating the module definition files.

Which command should I run before committing code to version control?

Run go mod tidy. This ensures that go.mod contains the minimal set of required dependencies and that go.sum includes only the checksums for those specific modules. This practice keeps the repository state clean and reproducible for other developers.

How do these commands handle the go.sum file differently?

go mod download writes checksum entries for any downloaded modules that were not already present in go.sum, but it does not delete any entries. In contrast, go mod tidy rewrites go.sum completely so that it contains checksums exactly for the modules required by the final go.mod, removing any unused entries in the process.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →