# Go Vendor Directory vs Go Modules: When to Use Each in Your Project

> Understand Go Modules and vendor directory differences. Use modules for standard dependency management and vendor for air-gapped builds or strict compliance.

- Repository: [golang-standards/project-layout](https://github.com/golang-standards/project-layout)
- Tags: deep-dive
- Published: 2026-03-06

---

**Use Go Modules for standard dependency management, and enable the vendor directory only when you require air-gapped reproducible builds or must satisfy strict compliance policies that mandate local source verification.**

The `golang-standards/project-layout` repository defines industry standards for organizing professional Go codebases, including authoritative guidance on managing third-party dependencies. While **Go Modules** (introduced in Go 1.11 and stabilized in Go 1.14) provides the modern default workflow using `go.mod` files and the module proxy, the **vendor directory** remains a valid strategy for environments requiring guaranteed offline builds or source code audits.

## How Go Modules Work

Go Modules declare dependencies in a `go.mod` file located at the repository root, allowing the Go toolchain to download packages automatically from the default module proxy (`https://proxy.golang.org`).

### Core Files and Commands

The module system relies on two primary files:

- **`go.mod`** – Declares the module path, Go version, and required dependencies with semantic versioning constraints.
- **`go.sum`** – Contains cryptographic checksums that ensure reproducible builds by verifying the exact content of downloaded modules.

To initialize and use modules:

```bash

# Initialize a new module

go mod init github.com/yourname/awesomeapp

# Add a dependency (updates go.mod and downloads the module)

go get github.com/sirupsen/logrus@v1.9.0

# Build automatically fetches from proxy or local cache

go build ./...

```

A typical `go.mod` file looks like this:

```go
module github.com/yourname/awesomeapp

go 1.22

require (
    github.com/sirupsen/logrus v1.9.0
    golang.org/x/net        v0.12.0
)

```

## How the Vendor Directory Works

Vendoring creates a self-contained copy of every dependency inside the repository under the `/vendor` directory, eliminating the need for network access during builds.

### Creating and Using Vendored Dependencies

According to the [`vendor/README.md`](https://github.com/golang-standards/project-layout/blob/main/vendor/README.md) in the `golang-standards/project-layout` repository, you populate the vendor directory using the modules system as the source of truth:

```bash

# Copy all dependencies from go.mod into ./vendor

go mod vendor

# Build using vendored code (required flag for Go < 1.14)

go build -mod=vendor ./...

# Run tests with vendored dependencies

go test -mod=vendor ./...

```

As noted in the repository's vendor documentation: *"Note that you might need to add the `-mod=vendor` flag to your `go build` command if you are not using Go 1.14 where it's on by default."* In Go 1.14 and later, the toolchain automatically detects and uses the `/vendor` directory if present, making the flag optional.

## Go Vendor Directory vs Go Modules: Key Differences

| Aspect | Go Modules | Vendor Directory |
|--------|------------|------------------|
| **Storage location** | Dependencies live in the module cache or proxy; `go.mod` tracks versions only. | Complete source code of dependencies copied into `/vendor` folder. |
| **Network requirement** | Requires internet access (or private proxy) on first build unless cache is warm. | Zero network access required after initial `go mod vendor` execution. |
| **Repository size** | Smaller; only commit `go.mod` and `go.sum`. | Larger; includes full source of all dependencies. |
| **Build command** | `go build ./...` | `go build ./...` (auto-detected in Go 1.14+) or `go build -mod=vendor ./...` |
| **Audit compliance** | Relies on checksums in `go.sum`. | Provides human-readable source code for security reviews. |

## When to Choose Each Approach

Follow this decision framework from the `project-layout` repository guidelines:

**Choose Go Modules when:**
- You have reliable network access or a private module proxy.
- You want smaller repository sizes and simpler CI/CD pipelines.
- You are building a library intended for public consumption (vendoring is optional for libraries).

**Choose the Vendor Directory when:**
- You need **air-gapped reproducible builds** without internet access.
- Your organization requires **source code audits** of every dependency (regulated environments, financial services, government).
- You are working behind a strict corporate firewall that blocks the public module proxy.

## Practical Implementation Workflow

### Standard Module Workflow

For most projects, commit only the module definition files:

```bash
go mod init github.com/yourorg/project
go get github.com/example/lib@v1.2.3
go mod tidy

# Commit go.mod and go.sum only

git add go.mod go.sum
git commit -m "Add dependencies"

```

### Vendor-Enabled Workflow

For offline or audited environments:

```bash

# After establishing dependencies in go.mod

go mod vendor

# Commit the vendor directory (optional: add to .gitignore if not needed)

git add vendor/ go.mod go.sum
git commit -m "Vendor dependencies for offline builds"

```

The root [`README.md`](https://github.com/golang-standards/project-layout/blob/main/README.md) in the `golang-standards/project-layout` repository specifically discusses both approaches in the **### /vendor** section, emphasizing that vendoring is a deliberate choice for specific constraints rather than the default pattern.

## Summary

- **Go Modules** (`go.mod`/`go.sum`) provide the default, network-based dependency management suitable for most modern Go projects.
- **Vendoring** (`go mod vendor` + `/vendor` directory) creates local copies of dependencies for offline builds and audit compliance.
- Go 1.14+ automatically uses the vendor directory when present; earlier versions require the `-mod=vendor` flag.
- The `golang-standards/project-layout` repository documents both strategies, with specific guidance in [`vendor/README.md`](https://github.com/golang-standards/project-layout/blob/main/vendor/README.md) regarding flag usage and Go version differences.
- Prefer modules for libraries and standard applications; prefer vendoring for regulated environments or air-gapped deployments.

## Frequently Asked Questions

### Do I need to commit the vendor directory if I already have go.mod?

No. If you use Go Modules, you only need to commit `go.mod` and `go.sum`. Commit the `/vendor` directory only if your build environment requires offline compilation or your security policy mandates local source verification. The `golang-standards/project-layout` repository treats vendoring as an optional addition to modules, not a replacement.

### What is the difference between go.sum and the vendor directory?

`go.sum` stores cryptographic hashes that verify the integrity of downloaded modules, while the vendor directory stores the actual source code files. The checksum file ensures you get the exact same bits from the network, whereas vendoring ensures you have those bits locally without network access.

### How do I build with vendored dependencies in older Go versions?

On Go versions prior to 1.14, you must explicitly pass the `-mod=vendor` flag to every build command: `go build -mod=vendor ./...`. Starting with Go 1.14, the toolchain automatically detects the `/vendor` directory and uses it by default, making the flag optional according to the [`vendor/README.md`](https://github.com/golang-standards/project-layout/blob/main/vendor/README.md) documentation.

### Should I use vendoring for a public library I am publishing?

Generally, no. Published libraries should use Go Modules and provide a clean `go.mod` file. Vendoring is primarily intended for applications or specific CI/CD pipelines where reproducibility without network access is critical. Consumers of your library will resolve dependencies through their own module proxy or cache.